Narrow type of property in subclass

Today I came across strange behavior that I did not expect from the Objective-C compiler.

In UITableViewCell, there is a property called imageView of type UIImageView. I have subclassed UITableViewCell and overwritten imageView, except that I made it of type AWImageView, where AWImageView is a subclass of UIImageView. I thought this would not compile, but it is. Everything works perfectly. I was very shocked by the behavior.

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

+4
source share
2 answers

Your suspicion that you are allowed to do this is reasonable, but in this particular case you are fine ...

In a strict interpretation of subtyping overrides, an overriding method can take arguments of a more general type and return a value of a more specific type.

For example, using Objective-C, given:

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

and method M in B:

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

then in class C with strict subtyping this can be overridden in class C using:

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

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

 B *bObj = ...; 

and then called method M:

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

whether bObj is actually B or C, then the call is correct in type - if it is an object C, then the argument being B is exact, since it is also A, and the result of C is exact like this is also B.

This leads us to not quite your property; in Objective-C, a property is simply a shorthand for two methods:

 @property B *myBvalue; 

is an abbreviation for:

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

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

 @property C *myBvalue; 

You are getting:

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

and the setMyBvalue: method violates the strict subtyping rule - casting an instance of C to an instance of B and the input rules say that you can pass B, the method expects C, and chaos can occur.

However, in your case, the property that you override is readonly , so there is no installation and no danger.

+5
source

if AWImageView inherits (subclasses) from UIImageView, then it is UIImageView, therefore everything remains the same for the compiler.

from documents:

enter image description here

Figure 1-1 [...] This just says that an object of type Square is not only a square, it is also a rectangle, shape, graphic, and an object of type NSObject.

+1
source

Source: https://habr.com/ru/post/1413862/


All Articles