Instance variable type different to property type?

Hi there!

I will appreciate very much if someone can shed light on why the instance variable type in BNREmployee.h is different to the property type. Here is the part of the code:

@interface BNREmployee : BNRPerson
{
     NSMutableArray *_assets;
}

@property (nonatomic, copy) NSArray *assets;

I’m sure readers of this book will know there are more properties and code involved, however, I’m only mentioning the above because I’m not understanding why there is a NSArray type in the property declaration. Should it not be a NSMutableArray type because after all _assets is pointing to a NSMutableArray?

In short I’m not understanding why the type of the property and the instance variable are not the same.

I will highly appreciate help on this. Thank you all in advance.

Kind regards,

Smiley.

[quote][code]@interface BNREmployee : BNRPerson
{
NSMutableArray *_assets;
}

@property (nonatomic, copy) NSArray *assets;
@end[/code][/quote]
There is no conflict here.

By declaring the type of assets property NSArray, BNREmployee class is in effect saying that
the external world can’t modify the array of assets. My declaring the type of the instance variable NSMutableArray, it is saying that
the implementation can modify the _assets array.

If you are using the latest version of the Objective-C, this is how you would declare the above interface:

[code]
@interface BNREmployee : BNRPerson

@property (nonatomic, copy) NSArray *assets;

@end[/code]
And you would hide the implementation details in the BNREmployee.m file, in one of the following ways:

... @implementation BNREmployee { NSMutableArray *_assets. } ... @end
Or this way:

...
@interface BNREmployee ()
{
   NSMutableArray *_assets.
}
@end

@implementation BNREmployee
...
@end

Ibex10, thank you very much for that. I think I’ve understood it now.

Regards,

Smiley.

I am new and don’t grasp it all, but why even declare any array in the header? If it is only declared in Portfolio.m then it would not have any public access except through accessors.

There might be times you want public access to the array. It just depends on what you are looking to achieve and what level of control you want to cede to those outside the class.

Hi!

Just wanted a confirmation, Ibex10, when you say “external world” I am presuming you don’t mean any subclasses of BNREmployee? I am saying that because subclasses would inherit all the instance variables and methods. Am I right in thinking this?

Many thanks,

Smiley.

Yes. However, subclasses can’t access superclass’s ivars directly if you make them private.

Compile this to see what you get:

//  main.m
#import <Foundation/Foundation.h>

@interface Foo : NSObject
{
    long _foo;
}

@property long foo2;

@end

@interface FooBar  : Foo

- (void)gobble;

@end

int main (int argc, const char * argv[])
{
    FooBar *fooBar = [FooBar new];
    [fooBar gobble];
    return 0;
}

@implementation Foo
{
    long _foo3;
}

@end

@implementation FooBar

- (void)gobble
{
    _foo = 0;
    self.foo2 = 0;
    
    // _foo2 and _foo3 are private ivars
    // Can't access them
    _foo2 = 0;
    _foo3 = 0;
}

@end

Ibex10, thank you very much for that. It greatly helped.

Enjoy your day!

Smiley.

[quote=“ibex10”]Yes. However, subclasses can’t access superclass’s ivars directly if you make them private.

Interesting. How would you access them then?

Also, should we be declaring instance variables in @interface or @implementation? You mentioned in the latest version of objective-C new ways of declaring. I have been following along with what the book does by declaring instance variables inside @interface and have had no problems. What is the reason for now putting declarations inside @implementation?

The whole point of declaring an ivar to be private is to prevent it from being accessed outside of the class that declared it. If you want subclasses to be able to access the ivar, and still protect it from access by unrelated code, it can be marked protected. Public ivars can be accessed by any code that makes use of the declaring class.