Questions about Class Extensions and inheritance in objective-c - objective-c

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 ?

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.

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.

Related

Simple Class Extension / Inheritance Clarification

I've been writing Objective-C for a few years now, and decided to go back and learn the very basics to help me write even better code. I'm trying to learn all about instance variables, inheritance and class extensions. I've been reading up on all three, but there is one thing that boggles my mind. I have a simple app that contains 2 classes, Person, Male (inherits from Person), and of course Main (which imports the Male class, therefore being able to access the instance variables found in both Person and Male).
The code is simple, and for the sake of space I won't post all of it. Basically Main takes these variables and plays around with them. This is the part that is boggling my mind:
#interface Person : NSObject {
float heightInMeters;
int weightInKilos;
}
#property float heightInMeters;
#property int weightInKilos;
#end
When I delete the brackets and variable declarations, leaving it like this:
#interface Person : NSObject
#property float heightInMeters;
#property int weightInKilos;
#end
The code still inherits and executes just fine.
1. What is the point of even declaring them there in the first place if we can just create two properties?
2. why create two instance variables AND properties to correspond with them?
3. I know that we can declare the variables in the .m instead to keep them private to the class and everything that subclasses it. like this:
#implementation Person {
float heightInMeters;
int weightInKilos;
}
What is the difference here? I feel like I'm missing a lot of basics. Is there a simplistic way of putting this all in perspective?
When you declare a #property, the compiler will automatically synthesize the variable prefixed with an underscore, a getter method, and a setter method.
#interface MyClass ()
#property(strong, nonatomic) NSString *myString;
#end
In this example the compiler would syhtnesize the variable as _myString, the getter as
-(NSString *)myString
and the setter as
-(void)setMyString:(NSString *)string
The keywords after "#property" (strong, nonatomic) define the property's attributes. strong, the default, implies ownership, meaning that in this case MyClass instances will essentially be responsible for the retain/release of their respective myString objects. nonatomic means the variable is not guaranteed to always be a valid value in a multithreaded environment, for example if the getter is called at the same time as the setter.
Additionally, the compiler will treat dot syntax used to retrieve/set instance variables as calls to the appropriate getter/setter methods. Therefore, given an instance of MyClass
MyClass *exampleClass = [[MyClass alloc] init];
Both of the following are equivalent statements:
NSString *string1 = example.myString; // dot syntax
NSString *string1 = [example myString]; // explicit call to the getter method
For further reading, take a look at Apple's Programming with Objective-C Guide.
As for your specific questions:
1. What is the point of even declaring them there in the first place if we can just create two properties?
It's actually not a good idea to declare variables explicitly as public variables in your MyClass.h file (or in most other cases). Instead, declaring them as properties automatically creates a private variable (and accessor methods), making adhering to OOP best practices a little easier. So there is no point in declaring
// MyClass.h
#interface MyClass : NSObject {
NSString *myString // public variables not good
}
Also because of what I stated above regarding dot syntax, if you use self.myString internally in MyClass.m or instanceOfMyClass.myString externally, the public variable myString will never even be touched because the synthesized variable is named _myString.
2. Why create two instance variables AND properties to correspond with them?
See above--you don't need two instance variables, only one.
3. I know that we can declare the variables in the .m instead to keep them private to the class and everything that subclasses it. What is the difference here? I feel like I'm missing a lot of basics. Is there a simplistic way of putting this all in perspective?
If you declare your variables privately in the #implementation part of your .m file, the compiler won't be able to help you by synthesizing the getters and setters. Even as private methods, getters and setters can help reduce complexity in your code, for example checking for the validity of variable values. (Note: you can override accessor methods.)
// MyClass.m
#interface MyClass () // private interface
#property(nonatomic, strong) NSString *myString;
#end
#implementation MyClass {
// no more need for private variables!
// compiler will synthesize NSString *_myString and accessors
}
-(void)setMyString:(NSString *)string { // overwrite setter
// no empty strings allowed in our object (for the sake of example)
NSAssert([string length] > 0, #"String must not be empty");
// assign private instance variable in setter
_myString = string;
}
#end
This way, even when you subclass MyClass, the subclass will inherit the getter and setter methods that were synthesized for us by the compiler.

private fields on Objective C

What is difference of these three cases (all of them are used like private fields):
1.
#interface APLParseOperation : NSOperation
#property (copy, readonly) NSData *earthquakeData;
#end
2.
#interface APLParseOperation () <NSXMLParserDelegate>
#property (nonatomic) APLEarthquake *currentEarthquakeObject;
#property (nonatomic) NSMutableArray *currentParseBatch;
#property (nonatomic) NSMutableString *currentParsedCharacterData;
#end
3.
#implementation APLParseOperation
{
NSDateFormatter *_dateFormatter;
BOOL _accumulatingParsedCharacterData;
BOOL _didAbortParsing;
NSUInteger _parsedEarthquakesCounter;
}
It's a good practice or smthing else?
I'm going to go through each example you gave, and describe them. I was just having trouble with this yesterday so I feel your pain.
1.
#interface APLParseOperation : NSOperation
#property (copy, readonly) NSData *earthquakeData;
#end
By using the #property keyword, the compiler automatically synthesizes your accessor methods for you, and also a backing instance variable. However, because you are using the readonly property attribute, the compiler is only synthesizing a getter method for you.
2.
#interface APLParseOperation () <NSXMLParserDelegate>
#property (nonatomic) APLEarthquake *currentEarthquakeObject;
#property (nonatomic) NSMutableArray *currentParseBatch;
#property (nonatomic) NSMutableString *currentParsedCharacterData;
#end
This second example is very similar to the first. However, because none of them have the readonly property attribute, they will all have getters and setter methods synthesized for them, as well as the backing instance variable.
3.
#implementation APLParseOperation
{
NSDateFormatter *_dateFormatter;
BOOL _accumulatingParsedCharacterData;
BOOL _didAbortParsing;
NSUInteger _parsedEarthquakesCounter;
}
For this last example, you are just declaring instance variables. These are also private to your implementation file, where as the other 2 examples had declarations being made in your classes interface file.
No setter or getter methods are being synthesized for you by the compiler. You are simply declaring some instance variables.
In terms of private and public, your first and second examples both provide declarations that will be visible to other classes, as long as they import the current class's header file. The first example however, only provides a way to "get" the property and read it, there is no setter method because you used the readonly property attribute. With the second example, outside classes will be able to access your getter and setter methods for your property, so they can read and write.
For the third example, these are just instance variables and they are private to your class's implementation file. Basically, no outside classes will even know that they exist.
This is not private. It is still readable by outside classes, though it can't be written.
Private properties. It can be useful if you want to write custom getters and setters. If you are not using ARC, it can be helpful for memory management.
Private members. This is my favorite. It's easy to read and easy to write.
defines a public property visible to all users of the APLParseOperation class.
defines properties through an extension, making them available only to the implementation methods.
defines instance variables which are implicitly private.
Number 1 is used when you want to make your properties public. Numbers 2 and 3 are for private properties and instance variables. You can also declare instance variables in class extensions, like this:
#interface APLParseOperation () <NSXMLParserDelegate>
{
NSDateFormatter *_dateFormatter;
BOOL _accumulatingParsedCharacterData;
BOOL _didAbortParsing;
NSUInteger _parsedEarthquakesCounter;
}
#end
There is not much difference between that and the number 3. It is a good idea to pick one style, and stick to it in all your code.
Case 1. is not private. It's a public read-only property: Reading is public, writing is only possible only in the private scope via the underlying ivar (thanks for pointing it out #mah).
Case 2. (if in a .m file) is extending the class by adding 3 private properties and making the protocol conformance private too.
Case 3. is declaring 4 private instance variables that can be used in all the implementation scope.
Objective-C best practice for private properties is case 2., as case 1. is not private at all, just read-only, and case 3. uses instance variables (aka ivar) which is less conventional than properties. More on that here: Reason to use ivars vs properties in objective c
Hope this helps,

#property vs just declaring getter and setter

Is there any difference in behaviour - either at compile time or at run time - between this code...
// MyClass.h
#interface MyClass : NSObject
#property (nonatomic) SomeType myProperty;
#end
// MyClass.m
#implementation MyClass
#end
... and this code?
// MyClass.h
#interface MyClass : NSObject
-(SomeType)myProperty;
-(void)setMyProperty:(SomeType)myProperty;
#end
// MyClass.m
#implementation MyClass {
SomeType _myProperty;
}
-(SomeType)myProperty {
return _myProperty;
}
-(void)setMyProperty:(SomeType)myProperty {
_myProperty = myProperty;
}
#end
Obviously, the former version is more succinct and readable, but is there any difference in behavior? Do the synthesized getter and setter do anything more sophisticated than my straightforward implementation here? Is the declaration of a property distinguishable by introspection functions from declaration of a getter and setter? Are there any other differences I haven't thought of?
Short answer: No difference. However, some property attributes (copy or atomic) may require different accessor methods.
Long answer: There is a group of introspection functions that allow you to access all #properties declared for given class or protocol:
class_getProperty
class_copyPropertyList
protocol_getProperty
protocol_copyPropertyList
property_getName
property_getAttributes
I don't think any of these functions is useful in production code, because this is basically an implementation detail of the class. Also, there may be a getter/setter exposed in the public interface and a private property hidden in class extension.
Oh, and there's one other difference: Xcode highlights properties and plain getters differently :)
One difference is memory management. You can configure your properties to for example copy the object being set or to use a weak variable. Your code seem to be assuming ARC is active, since you are not releasing the old object and retaining the new object.
Before ARC a typical setter would to something like
-(void)setMyProperty:(SomeType *)myProperty {
if (myProperty == _myProperty) return;
[_myProperty release];
_myProperty = myProperty;
[_myProperty retain];
}
When you say you use ARC, then there is only a small difference. But none that matters.
Your ivar is #protected.
A #property creates an ivar which is #private.
Generally speaking:
So when you subclass, it is possible for your subclass to directly access the ivar you created, but not the one the property created.
BUT since you put your ivar in the #implementation block, the ivar is never seen by the subclass.
Without ARC however and SomeType being not an Objective-C object, there is a big difference. Then your setter/getter wouldn't have retain/release messages included.

Objective-C: Compiler error when overriding a superclass getter and trying to access ivar

I'm working on building an iOS 6 app.
I have a class TDBeam which inherits from superclass TDWeapon.
The superclass TDWeapon declares a #property in the TDWeapon.h file:
#interface TDWeapon : UIView
#property (nonatomic) int damage;
#end
I do not explicitly #synthesize the property, as I'm letting Xcode automatically do so.
In the subclass TDBeam I override the getter in the TDBeam.m file:
#import "TDBeam.h"
#implementation TDBeam
- (int)damage {
return _damage;
}
#end
Xcode auto-completes the getter method name, as expected. But when I attempt to reference the _damage instance variable (inherited from the superclass), I get a compiler error:
Use of undeclared identifier '_damage'
What am I doing wrong here? I've tried explicitly adding #synthesize, and changing the name of the _damage ivar, but the compiler doesn't "see" it or any other ivars from the superclass. I thought ivars were visible and accessible from subclasses?
Synthesized ivars are not visible to subclasses, whether they are explicitly or automatically created: What is the visibility of #synthesized instance variables? Since they are effectively declared in the implementation file, their declaration isn't included in the "translation unit" that includes the subclass.
If you really want to access that ivar directly, you'll have to explicitly declare it (in its default "protected" form) somewhere that the subclass can see it, such as a class extension of the superclass in a private header.
There are a lot of posts on this topic on Stack Overflow, none of which offer simple concrete advice, but this topic sums it up most succinctly, and Josh's answer is the best in any.
What he kinda stops short of saying outright, is, if this is the kind of thing you want to do, don't use #property at all. Declare your regular protected variable in your base class as he says, and write you're own setters and getters if you need them. The ivar will be visible to any subclasses who can then write their own setters/getters.
At least that's where i've landed on the issue, although I'd a total newb to subclassing.
The idea of creating private headers to host your anonymous category and re-#sythesizing your ivars in your subclass just seems wrong on so many levels. I'm also sure I've probably missed some fundamental point somewhere.
Edit
Okay after some lost sleep, and inspired by Stanford's 2013 iTunes U course, here I believe is an example solution to this problem.
MYFoo.h
#import <Foundation/Foundation.h>
#interface MYFoo : NSObject
// Optional, depending on your class
#property (strong, nonatomic, readonly) NSString * myProperty;
- (NSString *)makeValueForNewMyProperty; //override this in your subclass
#end
MYFoo.m
#import "MYFoo.h"
#interface MYFoo ()
#property (strong, nonatomic, readwrite) NSString * myProperty;
#end
#implementation MYFoo
// Base class getter, generic
- (NSDateComponents *)myProperty {
if (!_myProperty) {
_myProperty = [self makeValueForNewMyProperty];
}
return _myProperty;
}
// Replace this method in your subclass with your logic on how to create a new myProperty
- (NSString *)makeValueForNewMyProperty {
// If this is an abstract base class, we'd return nil and/or throw an exception
NSString * newMyProperty = [[NSString alloc]init];
// Do stuff to make the property the way you need it...
return newMyProperty;
}
#end
Then you just replace makeValueForNewMyProperty in your subclass with whatever custom logic you need. Your property is 'protected' in the base class but you have control over how it is created, which is basically what you are trying to achieve in most cases.
If your makeValueForNewMyProperty method requires access to other ivars of the base class, they will, at the very least, have to be be public readonly properties (or just naked ivars).
Not exactly 'over-ridding a getter' but it achieves the same sort of thing, with a little thought. My apologies if, in trying to make the example generic, some elegance and clarity has been lost.

Difference between #interface declaration and #property declaration

I'm new to C, new to objective C. For an iPhone subclass, Im declaring variables I want to be visible to all methods in a class into the #interface class definition eg
#interface myclass : UIImageView {
int aVar;
}
and then I declare it again as
#property int aVar;
And then later I
#synthesize aVar;
Can you help me understand the purpose of three steps? Am I doing something unnecessary?
Thanks.
Here, you're declaring an instance variable named aVar:
#interface myclass : UIImageView {
int aVar;
}
You can now use this variable within your class:
aVar = 42;
NSLog(#"The Answer is %i.", aVar);
However, instance variables are private in Objective-C. What if you need other classes to be able to access and/or change aVar? Since methods are public in Objective-C, the answer is to write an accessor (getter) method that returns aVar and a mutator (setter) method that sets aVar:
// In header (.h) file
- (int)aVar;
- (void)setAVar:(int)newAVar;
// In implementation (.m) file
- (int)aVar {
return aVar;
}
- (void)setAVar:(int)newAVar {
if (aVar != newAVar) {
aVar = newAVar;
}
}
Now other classes can get and set aVar via:
[myclass aVar];
[myclass setAVar:24];
Writing these accessor and mutator methods can get quite tedious, so in Objective-C 2.0, Apple simplified it for us. We can now write:
// In header (.h) file
#property (nonatomic, assign) int aVar;
// In implementation (.m) file
#synthesize aVar;
...and the accessor/mutator methods will be automatically generated for us.
To sum up:
int aVar; declares an instance variable aVar
#property (nonatomic, assign) int aVar; declares the accessor and mutator methods for aVar
#synthesize aVar; implements the accessor and mutator methods for aVar
This declares an instance variable in your object:
#interface myclass : UIImageView {
int aVar;
}
Instance variables are private implementation details of your class.
If you want other objects to be able to read or set the value of the instance variable (ivar), you can declare it as a property:
#property int aVar;
This means that the compiler expects to see setter and getter accessor methods for the property.
When you use the #synthesize keyword, you are asking the compiler to automatically generate setter and getter accessor methods for you.
So, in this case the compiler will generate code similar to this when it encounters the #synthesize keyword:
- (int) aVar
{
return aVar;
}
- (void)setAVar:(int)someInt
{
aVar = someInt;
}
By default on the iPhone (and on the 32-bit runtime on the Mac), #synthesize requires an instance variable to be present in order to store the property's value. This ivar is usually named the same as the property, but doesn't have to be, for instance you could do this:
#interface myclass : UIImageView {
int aVar;
}
#property int someValue;
#synthesize someValue = aVar;
Neither #synthesize nor #property are actually required, you can create your own getter and setter methods, and as long as you create them using Key-Value Coding-compliant syntax, the property will still be usable.
The requirement for an ivar to be present as well as the #property declaration is due to the fragile base class limitation of the 32-bit Objective-C runtime on both the Mac and iPhone. With the 64-bit runtime on the Mac you don't need an ivar, #synthesize generates one for you.
Note that there are numerous keywords you can use with your #property declaration to control what sort of synthesized accessor code is created, such as readonly for a getter-only accessor, copy, atomic, nonatomic and so on. More information is in the Objective-C 2.0 Programming Language documentation.
Classes can have instance variables (ivars). These are in the first section, and are only visible to code in that class, not any outside code. I like to prefix them with an underscore to show their internal-ness. In low level terms, the ivars are added as an additional member to the struct that the class you are creating uses internally.
The second declaration, #property, is a declared property. It is not required (except when you are using #synthesize), but it helps other programmers (and the compiler!) know that you are dealing with a property, and not just two methods -setAVar and -aVar, which is the alternative way of doing this.
Thirdly, the #synthesize actually creates the methods to set and access the property from outside the class. You can replace this with your own setter and getter methods, but only do that if you need to, as the built-in ones have some features that you would otherwise have to code yourself. In fact, using the #synthesize aVar = _someVariable; syntax, you can have your property actually reference a differently named instance variable!
Short version:
The #property is just a hint to the compiler and other programmers that you are making a property and not just getter/setter methods. The instance variables are internal to the class, and otherwise cannot be normally accessed from outside it. The #synthesize just creates simple getters and setters for you, to go with your #property, but you can also just code those getters and setters yourself, like any other method.
Class A
#interface myclass : UIImageView {
int aVar;
}
If you declare like this then you can only use this variable within your class A.
But suppose in Class B
A *object=[A new];
object.aVar---->not available
For this you should **declare aVar as a property in Class A**
so class A should look like
Class A
#interface myclass : UIImageView {
int aVar;
}
#property int iVar;
and
.m file
#synthesize iVar;
So now you can use this iVar in another class Suppose B
Class B
#import "Class A.h"
enter code here
A *object=[A new];
object.aVar---->available
means
object.aVar=10;
#interface declares the instances variables of a class in obj-c. You need it to create an instance variable. However the variable is not visible outside the class by default (as the field is by default protected).
#property tells the compiler to specify a particular property accessor (get/set) method. However, you will need to use #synthesize to actually have the compiler generate the simple accessors automatically, otherwise you are expected to create them on your own.
I recently started learning iphone apps. As per my knowledge #property is used in .h file as a setter method and #synthesize in .m file as getter method. In Java we use setter and getter methods, same as Java, in Objective C we use #property and #synthesize.
Please forgive me If u think I mislead you.