Leem.fin
Leem.fin

Reputation: 42622

class extension in objective-c

I am learning object-c by reading a book. When I read the chapter about class extension, the book gives the following example code:

// A class extension
@interface BNREmployee ()

@property (nonatomic) unsigned int officeAlarmCode;

@end

@implementation BNREmployee
...
@end

The book says objects that are not instances of BNREmployee can no longer see this property officeAlarmCode. It makes an example:

BNREmployee *mikey = [[BNREmployee alloc] init];
unsigned int mikeysCode = mikey.officeAlarmCode;

This attempt would result in a compiler error that reads “No visible @interface declares the instance method officeAlarmCode”.

But I get confused. I mean I feel the book's words & its example code are contradictory. Book says objects that are not instance of BNREmployee can not longer see property officeAlarmCode. But in the example code above, isn't mikey an instance of BNREmployee? Why it cannot see officeAlarmCode event it is an instance of BNREmployee ?

=== UPDATE =====

The book I am reading is this one. Chapter 22, page 162.

I just want to verify that the book explained in a misleading way & I am looking for a clear explanation here. Because book says "objects that are NOT instance of BNREmployee can no longer see property officeAlarmCode", for the book reader like me, I feel it hints objects that are instance of BNREmployee CAN SEE property officeAlarmCode. That's why I am confusing, because mikey is an instance of BNREmployee but it can't access officeAlarmCode.

Upvotes: 2

Views: 13376

Answers (6)

Suhit Patil
Suhit Patil

Reputation: 12023

As per the Apple Docs 1. a class extension can add its own properties and instance variables to a class 2. Class extensions are often used to extend the public interface with additional private methods or properties for use within the implementation of the class itself.

so if you declare the property in class extension it will be visible only to the implementation file. like

in BNREmployee.m

@interface BNREmployee ()

@property (nonatomic) unsigned int officeAlarmCode;

@end

@implementation BNREmployee

- (void) someMethod {
    //officeAlarmCode will be available inside implementation block to use
     _officeAlarmCode = 10;
}
@end

If you want to use officeAlarmCode in other classes, let's say OtherEmployee class then you need to create officeAlarmCode property in BNREmployee.h file with readOnly or readWrite access. Then you can use it like

BNREmployee.h

@property (nonatomic, readOnly) unsigned int officeAlarmCode; //readOnly you can just read not write 

in OtherEmployee.m

import "BNREmployee.h"
@interface OtherEmployee ()

@property (nonatomic) unsigned int otherAlarmCode;

@end

@implementation OtherEmployee

you can create instance of BNREmployee and can assign officeAlarmCode value to otherAlarmCode property like below

BNREmployee *bnrEmployee = [BNREmployee alloc] init];
_otherAlarmCode = bnrEmployee.officeAlarmCode;

Upvotes: 3

onur surme
onur surme

Reputation: 132

BNREmployee *mikey = [[BNREmployee alloc] init];
unsigned int mikeysCode = mikey.officeAlarmCode;
  • This code is in a file. That file (and that class) isn't BNREmployee.m .This code is in a non-BNREmployee object. Lets call the object in which this code exists foo .
  • mikey is a BNREmployee object.
  • This code tries to access the officeAlarmCode property of a BNREmployee object.
  • When foo wants to use a BNREmployee object (like mikey), the properties it can access are only the ones in BNREmployee.h.
  • As officeAlarmCode doesn't exist in BNREmployee.h, foo cannot access the officeAlarmCode property of mikey, because this property isn't in the interface ( BNREmployee.h file).
  • As mikey is a BNREmployee object, it can see the officeAlarmCode, and use it.
  • Where is mikey's code which can use the officeAlarmCode? mikey's code is in BNREmployee.m file. So the only code that can use the officeAlarmCode is the implementation of BNREmployee.

Upvotes: 1

AndreVitorio
AndreVitorio

Reputation: 930

What I got from it is that the property officeAlarmCode is only visible within the BNREmployee.m file, it will not be accessible from main.m.

To pass the value to mikeysCode you would have to create a method that returns officeAlarmCode.

Upvotes: 0

A-Live
A-Live

Reputation: 8944

Think contexts, any other class can access the properties declared at the extensions or any categories as far as the extended interfaces are "visible" at the given context.

For example, the following implementation file contains implementation of two interfaces: BaseObject and BaseObjectController. At the implementation of the other class (BaseObjectController) you can safely use the "hidden" property via getters and setters because the declaration interface is "visible". If you move the implementation of BaseObjectController to another file that can't see declaration of the extension - this code won't compile.

#import "BaseObject.h"
#import "BaseObjectController.h"

//  BaseObject    
@interface BaseObject()
@property (strong) NSString * idString;
@end

@implementation BaseObject
@end

//  BaseObjectController    
@implementation BaseObjectController
- (void) initBaseObject {
    BaseObject * bo = [BaseObject new];
    bo.idString = @"01234";
}
@end

Upvotes: 0

Amin Negm-Awad
Amin Negm-Awad

Reputation: 16660

It is a little bit misleading to say "objects can no longer see". Objects doesn't see anything, even in the figurative sense. Let`s say: Code placed outside the implementation of the class cannot see the property.

Upvotes: 2

Abizern
Abizern

Reputation: 150615

Mikes is an instance of BNREmployee. But the example is telling you that the property officeAlarmCode is not exposed and can only be used by BNREmployee objects internally.

Upvotes: 4

Related Questions