1

I do not have anything in particular to achieve, but rather I am trying to learn more about class extension.

This is the explanation of class extension directly from apple Categories and extensions:

@interface MyClass : NSObject
@property (retain, readonly) float value;
@end

// Private extension, typically hidden in the main implementation file.
@interface MyClass ()
@property (retain, readwrite) float value;
@end

it does make perfect sense to me, however, supposing I have a MyClass2 extending MyClass:

@interface MyClass2 : MyClass
@property (retain, readwrite) float value;
@end

so I have few questions, which I could easily answer if class extensions weren't involved:

  • at runtime, when in MyClass I am doing an assignment self.value=2 or just calling float x=self.value , which setter and getter @property are called ? MyClass or MyClass2 ?
  • shouldn't the compiler at least issue a warning about a readonly property being redefined ?
  • I know @property are backed by an ivar, so how many ivar are there in the end ? Related to this, calling the same self.value from MyClass2 point of view which ivar would set ?
Leonardo
  • 9,607
  • 17
  • 49
  • 89
  • 1
    Please don't mark my answer as correct. I initially gave the wrong answer, and corrected it only after Martin R put me right. – emrys57 Nov 22 '12 at 18:55

2 Answers2

1

First off, the properties should be 'assign' not 'retain' since they are scalar types.

Changing the writability in class extensions or subclasses are common patterns to implement publicly read-only but privately writable properties and mutable subclasses of immutable classes, respectively. The Apple Objective-C Programming Guide has a good discussion.

To answer your first question, only methods declared in MyClass, or any of its super-classes, are visible from within MyClass. Your private class extension declares the setter in scope to the implementation, so that will get called. The readwrite declaration in the interface for MyClass2 merely brings the setter in to the public scope. The implementation is still in MyClass.

The answer to your second question is no, a warning is not issued. Changing writability from read-only to read-write is valid.

Finally, there is only one ivar. Accessing it from MyClass2 affects the same ivar visible in MyClass.

BradS
  • 1,935
  • 1
  • 13
  • 13
  • I didn't notice that, I agree with you about scalar type, however this is a sample from Apple doc :-) – Leonardo Nov 23 '12 at 09:52
  • At this point, I wonder what are the benefit of class extensions, if I can extend a class and transform a readonly to public. Vanishing the purpose of protecting a readonly property. – Leonardo Nov 23 '12 at 10:03
0

You can't retain a float. Let's write (readonly) instead.

MyClass doesn't know anything about MyClass2, which seems to be a subclass of MyClass. When you write self.value = 2, it will be transformed into [self setValue:2] and the code will start at MyClass and look for a setValue method. This will have been created, because you defined value as a property. The setter method will look like

-(void) setValue:(int newValue) {
      _value = newValue; // _value is the actual storage for the property value
}

and the variable _value will be the one allocated in the instance of the object MyClass that you are executing.

In fact there is just one iVar. If, In MyClass2, you write

self.value = 3;
super.value = 4;
float myFloat = self.value;

myFloat ends up equal to 4.

Presumably the compiler doesn't complain about redefining the property in MyClass because it's quite a reasonable thing to do. That way, other classes cannot write to value, but within MyClass, you can write self.value = 2; and it will work.

I did believe there were two iVars, but I was wrong. Sorry for confusing anyone. Thanks to Martin R and BradS for educating me.

emrys57
  • 6,679
  • 3
  • 39
  • 49
  • This answer is not correct. There is no second ivar in the subclass for the value property, and the subclass has no separate accessor functions. `anObject.value` will always reference the accessor functions in `MyClass`, even if `anObject` is an instance of `MyClass2`. – Martin R Nov 22 '12 at 18:03
  • But I just compiled and ran it and there were two! – emrys57 Nov 22 '12 at 18:04
  • I do not understand your example. If you have two different objects (object1 and object2), then of course each object has its own instance variable. – Martin R Nov 22 '12 at 18:07
  • Try "p *object2" in the Xcode debugger window, and you see that object2 has only one ivar (from the superclass MyClass). – Martin R Nov 22 '12 at 18:10
  • Sorry, you are, of course, correct. I retract my assertion. There is one iVar. – emrys57 Nov 22 '12 at 18:10