Access private instance variable of parent class - objective-c

I can't figure out why class B can access class A private instance variable.
Here is my code
A.h
#import <Foundation/Foundation.h>
#interface A : NSObject
{
#private
int x;
}
#property int x;
-(void)printX;
#end
A.m
#import "A.h"
#implementation A
#synthesize x;
-(void)printX
{
NSLog(#"%i", x);
}
#end
B.h
#import "A.h"
#interface B : A
{
}
#end
main.m
B *tr = [[B alloc] init];
tr.x = 10;
[tr printX];
Here I can access instance variable of A class x despite it is declarated as private ?

You are not accessing the private variable there, at least not directly: you are accessing a public property, which has legitimate access to the private ivar.
Your code is equivalent to this:
B *tr = [[B alloc] init];
[tr setX:10];
[tr printX];
The #synthesize statement created the getter and the setter methods for you. If you want only a getter to be available, mark your property readonly, and do all writings through an ivar in the A class.

In your implementation file do this on the top..
#interface A : NSObject
{
#private
int x;
}
#property int x;
#end
this way x will be private since it is in the implementation file. not the interface section...all classes import the interface section of A ..so it's variable are accessible to its subclasses.

Related

Objective-C public get set method for private property

I wonder if it is possible to use #synthesize on a private #property so that the get/set methods have public access.
Right now my code looks something like this
SomeClass.h
#import <Foundation/Foundation.h>
#interface SomeClass : NSObject
{
#private
int somePrivateVariable;
}
#end
SomeClass.m
#import "SomeClass.h"
#interface SomeClass ()
#property int somePrivateVariable;
#end
#implementation
#synthesize somePrivateVariable;
#end
Then in some outside function I want to be able to write:
#import "SomeClass.h"
SomeClass *someClass = [[SomeClass alloc] init];
[someClass setSomePrivateVariable:1337]; // set the var
NSLog("value: %i", [someClass getSomePrivateVariable]); // get the var
I know that I can just create my own get/set methods in the header file but I would enjoy using the #synthesize very much more.
If you want a public property to mirror a private one, just override the public property's getter and setter and return the private one.
#interface Test : NSObject
#property NSObject *publicObject;
#end
Then, in the implementation:
#interface Test ()
#property NSObject *privateObject;
#end
#implementation Test
- (NSObject *)publicObject
{
return self.privateObject;
}
- (void)setPublicObject:(NSObject *)publicObject
{
self.privateObject = publicObject;
}
#end

Understanding private instance variable

I'm having a hard time understanding private instance variables through example. After reading about private instance variables, I went to Xcode and tried to verify how they work.
In the book I'm reading, it states that if you declare an instance variable in the implementation file of a superclass, the instance variable will be private and inaccessible to subclasses.
I tried proving it doing the following without any luck.
/** SuperClass interface file**/
#import <Foundation/Foundation.h>
#interface ClassA : NSObject
-(void) setX;
-(void) printX;
#end
/**SuperClass implementation file **/
#import "ClassA.h"
#implementation ClassA
{
int x;
}
-(void) setX
{
x = 100;
}
-(void) printX
{
NSLog(#" x is equal to %i", x);
}
#end
/** interface file of subclass **/
#import "ClassA.h"
#interface ClassB : ClassA
#end
/**Main file **/
#import "ClassA.h"
#import "ClassB.h"
int main(int argc, const char * argv[])
{
#autoreleasepool
{
ClassA * a;
a = [[ClassA alloc] init];
ClassB * b;
b = [[ClassB alloc] init];
[b setX];
[b printX];
}
return 0;
}
The program prints the following:
x is equal to 100
isn't "x" a private instance variable and inaccessible by object "b", because "x" is declared in the implementation file of superClass "a" while "b" is a subclass?
The books says "instance variables that are to be accessed directly by a subclass must be declared in the interface section and not in the implementation section...Instance variables declared or synthesized in the implementation section are private instance variables and are not directly accessible by subclasses."
Really confused by this.
The methods setX and printX are public and visible and thus can be called on the instance of ClassB. Since they are public they can also be called by the ClassB, like this.
#implementation ClassB
- (void)fig {
[self setX];
}
#end
What can't be done is for ClassB to directly access the value x. Like this:
#implementation ClassB
- (void)foo {
NSLog(#"x is now %i", x);
}
#end
ClassB does not have direct access to x, but it has indirect access to x through the superclass methods. This indirect access is an object oriented programming concept known as encapsulation.
Ivars have #protected attribute by default, means subclasses can access them. To declare ivar as private, use #private attribute before ivar declaration:
#interface ClassA : NSObject
{
#private
int x;
}
If you declare your ivars in #implementation section, the only way for them to be visible to subclasses is to import .m file in your subclass, but your can't use them because they're private.
Or don't use ivars at all, since Objective-C properties now create ivars automatically. If you need a private property, you can declare it via anonymous category in .m file like this:
#interface MyClass ()
#property (nonatomic) NSInteger x;
#end
UPDATE:
I think I understand what's confusing you. Public and protected ivars are inherited by subclasses and can be accessed directly as instance variables of subclass, no need to use accessor methods from a subclass.

ObjectiveC: where to declare private instance properties?

I have the following class interface:
#interface MyClass : NSObject
#property int publicProperty;
#end
then the implementation:
#interface MyClass() // class extension
- (void)privateMethod; // private methods
#end
#implementation MyClass {
int _privateProperty;
}
#property int privateProperty = _privateProperty;
#end
this is what the Apple guy showed in WWDC, but is there any reason for NOT putting _privateProperty in class extension like:
#interface MyClass() // class extension
{
int _privateProperty;
}
- (void)privateMethod; // private methods
#end
Thanks!
I usually "force" private with an extension in the implementation
In your header
#interface MyClass : NSObject
{
}
#property (nonatomic, assign) int publicProperty;
#end
In your implementation file:
#interface MyClass ()
#property (nonatomic, assign) int privateProperty;
#end
#implementation MyClass
#synthesize privateProperty;
#synthesize publicProperty;
#end
You dont have to declare your ivars in both the interface and the implementation.Because you want to make them private you can just declared them in the implementation file like so:
#implementation {
int firstVariable;
int secondVariable;
...
}
//properties and code for your methods
If you wanted to, you can then create getter and setter methods so that you can access those variables.
The person you spoke to was right, though there is not any reason why you would NOT declare them the same way in the interface. Some books actually teach you that the #interface shows the public face of the class and what you have in the implementation will be private.
Do you mean you want to declare private instance variables?
You can do this:
#interface MyClass()
{
#private //makes the following ivar private
int _privateProperty;
}
With the "modern runtime" (64-bit MacOS post-10.5 and all versions of iOS), you don't need to declare instance variables at all.
// MyClass.h
#interface MyClass : NSObject
#property int publicProperty;
#end
// MyClass.m
#implementation MyClass
#synthesize publicProperty = _privateProperty; // int _privateProperty is automatically synthesized for you.
#end

Global Variables in Objective C

I have a counter which I use to get an object at that counters index and I need to access it in another class.
How are static variables declared in Objective C?
Rather than make it global, give one class access to the other class's counter, or have both classes share a third class that owns the counter:
ClassA.h:
#interface ClassA {
int counter;
}
#property (nonatomic, readonly) int counter;
ClassA.m
#implementation ClassA
#synthesize counter;
ClassB.h:
#import "ClassA.h"
#interface ClassB {
ClassA *a;
}
ClassB.m:
#implementation ClassB
- (void)foo {
int c = a.counter;
}
Hi alJaree,
You declare a static variable in the implementation of Your class and enable access to it through static accessors:
some_class.h:
#interface SomeClass {...}
+ (int)counter;
#end
some_class.m:
#implementation SomeClass
static int counter;
+ (int)counter { return counter; }
#end

How can I access variables from another class?

There is probably a very simple solution for this but I can't get it working.
I have got multiple classes in my Cocoa file. In one of the classes class1 I create a variable that I need to use in another class class2 as well. Is there a simple way to import this variable in class2?
You can either make the variable public, or make it into a property. For example, to make it public:
#interface Class1
{
#public
int var;
}
// methods...
#end
// Inside a Class2 method:
Class1 *obj = ...;
obj->var = 3;
To make it a property:
#interface Class1
{
int var; // #protected by default
}
#property (readwrite, nonatomic) int var;
// methods...
#end
#implementation Class1
#synthesize var;
...
#end
// Inside a Class2 method:
Class1 *obj = ...;
obj.var = 3; // implicitly calls [obj setVar:3]
int x = obj.var; // implicitly calls x = [obj var];
You could expose the variable in class2 as a property. If class1 has a reference to class2, class1 can then see the variable. Honestly, though, it sounds like you're a beginner to both Objective-C and object oriented programming. I recommend you read up more on both.
Here is a place to start for object oriented programming with Objective-C.
try making a file that holds your variables that need to be accessed throughout the app.
extern NSString *stringVariable;
#interface GlobalVariables
#property (retain, nonatomic) NSString *stringVariable;
#end
and in the GlobalVariables.m file add
#import "GlobalVariables.h"
#implements GlobalVariables
#synthesize stringVariable;
NSString *stringVariable;
#end
And then as long as you import GlobalVariables.h into which ever .m files you need to access that variable in you can assign and access anywhere throughout your program.
EDIT
My answer that I have given above is differently not the way I would go about doing this now.
It would be more like
#interface MyClass
#property (nonatomic, strong) NSString *myVariable;
#end
then in the .m file
#implementation MyClass
#sythesize = myVariable = _myVariable; // Not that we need to do this anymore
#end
Then in another class in some method I would have
// .....
MyClass *myClass = [[MyClass alloc] init];
[myClass setMyVariable:#"My String to go in my variable"];
// .....
In "XCode" you need to make import, create object by declaring it as the property, and then use "object.variable" syntax. The file "Class2.m" would look in the following way:
#import Class2.h
#import Class1.h;
#interface Class2 ()
...
#property (nonatomic, strong) Class1 *class1;
...
#end
#implementation Class2
//accessing the variable from balloon.h
...class1.variableFromClass1...;
...
#end
Thanks! :-)