2010-06-22 103 views
1

这可能是Java编码器报告的常见Objective-C问题,但我不知道该怎么称呼它或如何搜索答案。比方说,我有一个类和延伸它的另一个类:覆盖Objective-C中的继承类型

AbstractModel

@interface AbstractModel { 
} 

ModelImpl

@interface ModelImpl : AbstractModel { 
} 

分开这些,我还有两节课,再一个延伸另一种:

ControllerA

@interface ControllerA { 
    AbstractModel *foo; 
} 

@property (nonatomic, retain) AbstractModel *foo; 

ControllerB

@interface ControllerB : ControllerA { 
} 

我希望能够说foo在ControllerA可以包含AbstractModel或其任何亚型。但是,如果我尝试在其中存储AbstractModel以外的任何内容,编译器会给我一个警告。 (当然,我明白,类不能真正在ObjC是抽象的,但饶了我吧。)

我也想能够在特定的子类,以“锁定”的foo属性。我想说的是,ControllerB中的foo例如只能包含ModelImpl4。这可能吗?

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

+0

看看UITableView如何处理委托属性的例子。在这种情况下,它是一个协议,但它会和一个类一样好。 – drawnonward 2010-06-22 18:35:20

回答

3

首先,我想明白了这一点:

但是,如果我尝试存储任何东西,编译器会给我一个 警告 以外的AbstractModel。

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

接下来,你所描述的不是重写,而是超载。你试图改变方法的返回类型,并且你不能在ObjC中做到这一点。这个问题有很好的解决方法,但是它有点取决于你真正的目标是什么。

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

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

不要忽略警告。他们在那里保护你(而在ObjC中,他们就是你必须保护你的一切)。尽可能地限制你的类型转换。它们将编译器错误(良好)移至运行时异常(错误)。

+0

警告也可能来自他没有导入ModelImpl的头文件。我只是想到了。 – huntaub 2010-06-22 18:51:00

1

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

foo = (AbstractModel *)thisIsAModelImpl; 

然后,以“锁定下来”的ControllerB,您只需将这个行添加到您的.h文件中

ModelImpl *foo; 

而且,你会想覆盖(重新定义)ControllerB中处理foo的任何方法。

编辑:为了清楚起见,这是我的意思是覆盖。

如果你有方法(在ControllerA

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

你会改变那些行(在ControllerB

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