3

我有一个名为 的类AbstractBook,它有一个属性:

@property(strong) AbstractPage *page;

现在说我有一个AbstractBook被调用WhiteBook的子类和一个被调用的子AbstractPageWhitePage。我希望WhiteBook类继承page对象,但在这个类中,我希望它是特定WhitePage类而不是AbstractPage.

因此,在 中WhiteBook,我只是将属性重新声明为WhitePage

@property(strong) WhitePage *page;

但是,我收到一个警告:WhitePage is incompatible with AbstractPage inherited from AbstractBook.实现我的目标的正确方法是什么?

4

4 回答 4

5

你想做的事情基本上是不可能的。不要忘记这一点:

@property(strong) AbstractPage *page;

声明一个 getter和一个 setter

一般来说(这通常是针对 OO 编程,而不仅仅是 Objective-C),重写 getter 返回超类实现的返回类型的子类是没有问题的,因为这不会破坏 API 契约。在你的情况下,一个实例WhitePage也是一个AbstractPage.

但是,setter 不同。您不能限制参数的类型,因为您的子类必须在使用 anAbstractBook的任何地方都可用,因此在它认为是 an 的东西上调用 setter 的代码AbstractBook有权传入任何子 AbstractPage类的实例,因为这就是API说。

我想我会做的是添加一个方法来AbstractBook调用类似的东西

-(bool) isLegalPage: (AbstractPage) aPage;

始终在基类中返回 true,但仅在WhiteBook. 然后我将手动实现设置器,如下所示:

-(void) setPage: (AbstractPage*) aPage
{
    if (![self isLegalPage: aPage])
    {
        // throw an exception or do other error notification
    }
    else
    {
        Do the assignment according to reference count/ARC/GC model
    }
}

记录如果页面不合法,setter 将抛出异常,并且人们应该使用该isLegalPage:方法进行测试。

替代 id 具有只读属性并在基类和子类中使用不同的设置器,或者在基类中根本没有设置器。

于 2012-07-23T16:11:39.463 回答
3

Objective C中没有属性类型协方差,所以如果你想要一个属性返回 的子类AbstractPage,你需要whitePage在你的WhiteBook子类中定义一个单独的属性,比如 。page您也可以从您的财产中返回相同的值,并且它会起作用。此外,如果您的用户在 上调用方法AbstractPage*,他们甚至不需要将其强制转换为WhitePage*.

于 2012-07-23T15:20:36.833 回答
2

请记住对接口而不是实现进行编程。

=======================

选项1

如果您的 Whitebook 确实是 AbstractBook 的后代,您不需要让 WhiteBook 有一个名为“page”的新属性,因为您的 AbstractBook 已经声明它是您的 WhiteBook 免费获得的。

只要您的 WhitePage 从 AbstractPage 继承,您就应该能够将您的页面对象转换为 WhitePage。然后您将获得 AbstractPage 的所有原始功能,以及 WhitePage 的所有功能。

因此,您不需要在 Whitebook 中重新声明页面。如果您转到 Whitebook.h 文件并删除此行

@property(strong) WhitePage *page;

然后进入你的 Whitebook.m 文件并输入 self.page 你不应该得到任何编译警告。然后你可以将页面转换为 WhitePage,你应该很高兴。

警告:这意味着您需要在任何使用它的地方将页面转换为 WhitePage,这并不理想。

=======================

选项:2

您也可以尝试将代码保留原样,但请确保在 WhiteBook 中再次合成“页面”道具。

=======================

选项:3

您也可以尝试保留现有代码,但请确保在 WhiteBook 中将 @dynamic 用于“页面”属性。然后自己实现 getter 并返回 WhitePage 而不是 AbstractPage。

于 2012-07-23T15:22:43.313 回答
0

如何用更具体的类型覆盖超类的属性?

通常,如果您在@synthesize您的AbstractBook班级和班级中使用,它应该可以正常工作(当然,除非您使用综合方法来分配非to )。@dynamicWhiteBookAbstractPageWhitePagepage

于 2012-07-23T15:05:23.857 回答