覆盖Objective-C中的继承类型

时间:2010-06-22 18:10:18

标签: objective-c inheritance types polymorphism

这可能是Java编码员报告的一个常见的Objective-C问题,但我不知道该怎么称呼它或如何搜索答案。假设我有一个类和另一个扩展它的类:

AbstractModel

@interface AbstractModel {
}

ModelImpl

@interface ModelImpl : AbstractModel {
}

除了这些之外,我还有两个类,另一个扩展另一个类:

ControllerA

@interface ControllerA {
    AbstractModel *foo;
}

@property (nonatomic, retain) AbstractModel *foo;

ControllerB

@interface ControllerB : ControllerA {
}

我希望能够说ControllerA中的foo可以包含AbstractModel或其任何子类型。但是,如果我尝试在其中存储除AbstractModel之外的任何内容,编译器会给出警告。 (当然我理解,在ObjC中,类不能真的是抽象的,而是怜悯我。)

我还希望能够“锁定”特定子类中的foo属性。我想说,ControllerB中的foo只能包含一个ModelImpl4。这可能吗?

解决此类问题的常规Objective-C最佳实践是什么?以这种方式使用继承 - 或者实现这个目标 - 在Objective-C中不是一个好主意吗?

2 个答案:

答案 0 :(得分:3)

首先,我想理解这一点:

  

然而,编译器给了我一个   如果我试图存储任何东西警告   除了它中的AbstractModel。

这没有意义。您应该能够毫无困难地将AbstractModel的子类分配给foo。你看到了什么问题?

接下来,你所描述的并不是重写,而是超载。您正在尝试更改方法的返回类型,而您无法在ObjC中执行此操作。这个问题有很好的解决方案,但在某种程度上取决于你的真正目标。

  • 首先,您可以摆脱-foo中的ControllerA。如果ControllerA实际上是抽象的,那么最好不要有一个。如果ControllerA是抽象的,我绝对建议你摆脱该层的foo ivar。你应该将ivars放在子类中。

  • 或者,您可以将类型化方法添加到子类中。例如,ControllerB除了继承的-modelBFoo之外还有-foo方法。这些方法是相同的;他们会有不同的回报类型,允许在所有来电者中打字。

不要忽略警告。他们在那里保护你(在ObjC,他们是你必须保护你的全部)。尽可能限制你的类型转换。他们将编译器错误(好)转移到运行时异常(坏)。

答案 1 :(得分:1)

是。解决第一个问题的最简单方法就是忽略编译器警告。它将在运行时工作。如果您不喜欢这些警告,可以进行类型转换:

foo = (AbstractModel *)thisIsAModelImpl;

然后,要为ControllerB“锁定”,您只需将此行添加到.h文件中

ModelImpl *foo;

并且,您希望覆盖(重新定义)foo中处理ControllerB的任何方法。

编辑:为了清楚起见,这就是我所说的重写。

如果你有方法(在ControllerA

-setFoo:(AbstractModel *)newModel;
-(AbstractModel *)foo;

您可以将这些行更改为(ControllerB

-setFoo:(ModelImpl*)newModel;
-(ModelImpl*)foo;