您怀疑被允许这样做是有根据的,但是在这种特殊情况下,您可以...
在重写的严格子类型解释中,重写方法可以接受更通用类型的参数并返回更具体类型的值。
例如,使用 Objective-C,给出:
@interface A : NSObject { ... }
@interface B : A { ... }
@interface C : B { ... }
和B中的方法M:
- (B *) M:(B *)arg { ... }
然后在严格子类型下的 C 类中,这可以在 C 类中使用:
- (C *) M:(A *)arg { ... }
这是安全的,因为如果你有一个明显 B 对象的引用:
B *bObj = ...;
然后方法 M 调用:
B *anotherBObj = [bObj M:[B new]];
那么无论bObj
实际上是 B 还是 C,调用的类型都是正确的 - 如果它是 C 对象,那么作为 B 的参数很好,因为它也是 A,结果是 C 很好,因为它也是 B。
这使我们不完全是您的财产;在 Objective-C 中,属性只是两种方法的简写:
@property B *myBvalue;
是以下的简写:
- (void) setMyBvalue:(B *)value;
- (B *) myBvalue;
如果该属性在 B 中声明,并且您在 C 类中使用 C 值属性覆盖它:
@property C *myBvalue;
你得到:
- (void) setMyBvalue:(C *)value;
- (C *) myBvalue;
并且该方法setMyBvalue:
违反了严格的子类型化规则——将一个 C 实例转换为一个 B 实例,而类型化规则说你可以传递一个 B,该方法需要一个 C,然后就会出现混乱。
但是,在您的情况下,您要覆盖的属性是readonly
,因此没有设置器,也没有危险。