子类中的窄类型属性 [英] Narrow type of property in subclass

查看:93
本文介绍了子类中的窄类型属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天我遇到了一个我不希望Objective-C编译器允许的奇怪行为。

Today I came across a strange behavior that I did not expect Objective-C compiler would allow.

在UITableViewCell中,有一个名为imageView的属性为UIImageView。我将UITableViewCell子类化,并覆盖了imageView,除了我的AWImageView类型,其中AWImageView是UIImageView的子类。我认为它不会编译,但确实如此。一切正常。我对这种行为感到非常震惊。

In UITableViewCell, there is a property named imageView of the type UIImageView. I subclassed UITableViewCell, and overwrote imageView, except I made it of the type AWImageView where AWImageView is a subclass of UIImageView. I thought it would not compile, but it does. Everything works just fine. I was very much shocked by the behavior.

正在缩小正式允许的子类中的属性类型?或者这是Objective-C编译器中的一个错误吗?

Is narrowing the type of property in subclass allowed officially? Or is this a bug in Objective-C compiler that made it work?

推荐答案

你怀疑被允许这样做很好成立,但在这个特定的情况下,你没事......

Your suspicion of being allowed to do this is well founded, but in this particular case you are OK...

在重写的严格子类型解释中,一个重写方法可能接受更一般的类型并返回更具体类型的值。

In a strict subtyping interpretation of overriding, an overriding method may accept arguments of more general type and return a value of more specific type.

例如,使用Objective-C,给定:

For example, using Objective-C, given:

@interface A : NSObject { ... }
@interface B : A { ... }
@interface C : B { ... }

和B中的方法M:

- (B *) M:(B *)arg { ... }

然后在严格子类型下的C类中,可以使用以下方法在C类中覆盖:

then in class C under strict subtyping this could be overridden in class C using:

- (C *) M:(A *)arg { ... }

这是安全的,因为如果你有一个参考显然是B对象:

This is safe because if you have a reference to an apparently B object:

B *bObj = ...;

然后调用方法M:

B *anotherBObj = [bObj M:[B new]];

然后 bObj 实际上是B还是一个C调用类型是正确的 - 如果它是一个C对象那么参数是B是好的,因为它也是A,结果是C很好,因为它也是B。

then whether bObj is actually a B or a C the call is type correct - if it is a C object then the argument being a B is fine as it's also an A, and the result being a C is fine as it's also a B.

这使我们,不完全,你的财产;在Objective-C中,属性只是两种方法的简写:

Which brings us to, not quite, your property; in Objective-C a property is just a shorthand for two methods:

@property B *myBvalue;

是简写:

- (void) setMyBvalue:(B *)value;
- (B *) myBvalue;

如果该属性在B中声明,并且您在C类中使用C值属性覆盖它:

If that property is declared in B and your override it in class C with a C-valued property:

@property C *myBvalue;

你得到:

- (void) setMyBvalue:(C *)value;
- (C *) myBvalue;

且方法 setMyBvalue:违反严格规定子类型规则 - 将一个C实例强制转换为一个B实例,并且输入规则说你可以传递一个B,该方法需要一个C,然后就会出现混乱。

and the method setMyBvalue: violates the strict subtyping rule - cast a C instance to a B instance and the typing rules say you can pass a B, the method expects a C, and chaos can ensue.

但是在您的情况下,您覆盖的属性是 readonly ,因此没有setter,也没有危险。

However in your case the property you are overriding is readonly, so there is no setter, and no danger.

这篇关于子类中的窄类型属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆