0

From the developer that started to learn objective-c two days ago, I don't understand the difference between the following two methods :

1.

 @interface Person : NSObject

   @property NSString *firstName;
   @property NSString *lastName;

 @end

2.

  @interface Person : NSObject{

    NSString *firstName;
    NSString *lastName;
  }

 @end

Using Java-Language,we define two String Field:

class Person extends Object{
  (public/private/protected) String firstName;
  (public/private/protected) String lastName;
}

I want to know which one(between 1 and 2) has same meaning with the Java code above.


Very thanks for @iamyogish @Popeye,if my answer is right i will correct both of you. After read the eBook: Objective-C 2.0 Essentials,I learned that(if it is not right,you tell me. ):

@interface Person : NSObject

   @property NSString *firstName;
   @property NSString *lastName;

 @end

this is equivalent to the Java Code:

class Person extends Object{
 private  String firstName;
 private String lastName;//In fact:private should be protected
 //setter and getter.
 //you can use ecplise tool to generate setter/getter method automaticly
}

As you can probably imagine, having to write these methods for large numbers(1000 or more.)of complex classes will ultimately prove to be time consuming. Objective-C provides synthesized accessor methods,so what you should is use of the @property and @synthesize directives.if you write your code like this:

@interface Person : NSObject

    NSString *firstName;//note that the default access level is protected.
    NSString *lastName;

 @end

Unfortunatly, you need to provide methods that can access instance variables,such as(you can define the name of the function by yourself)

-(NSString ) getFirstName;
-(NSString ) getLastName;
-(void) setFirstName:(NSString * name);
-(void) setLastName:(NSString * name);

In addition to this,if the @property and @synthesize directives are used,you can access instance variables like C++/JAVA syntax dot notationsuch as:

 NSString * firstName= [[Person alloc] init].firstName;

Note that: A key point to understand about dot notation is that it only works for instance variables for which synthesized accessor methods have been declared.

The access level for instance variables is specified in the @interface section of the class declaration using the @protected, @private and @public directives.

 @interface Person : NSObject
 @public
    NSString *firstName;//note that the default access level is protected.
    NSString *lastName;

 @end

When accessing a public instance variable from another class or any other code in a methods or function, the -> pointer operator notation is used. So you can access the Public Filed in C++/C like:

  [[Person alloc] init]->firstName = "your first name";

Another question is:

  @interface Person : NSObject

   @property NSString *firstName;
   @property NSString *lastName;

 @end

is is equivalent to:

@interface Person : NSObject{
   NSString *firstName;
   NSString *lastName;
 }

   @property NSString *firstName;
   @property NSString *lastName;

 @end

or not? and ivar is equivalent to instance variable or not?

wyf
  • 75
  • 8
  • I start to learn Objective-C two days ago. – wyf Jan 10 '14 at 07:23
  • have a look at this SO question [link](http://stackoverflow.com/questions/508735/absence-of-property-syntax-in-java) – Bamsworld Jan 10 '14 at 07:25
  • I have seen it ,but i even don't understand it. – wyf Jan 10 '14 at 07:44
  • You don't need to use number 2 anymore. It's obsolete. – Desdenova Jan 10 '14 at 08:16
  • Oh, my god! The mechanism of setter and getter for Objective-C is similar to C# – wyf Jan 10 '14 at 08:37
  • If you are going to do your own answer it is best to use actually answer your question don't amend your question it will just add confusion. `ivar` is shorthand for `instance variable` – Popeye Jan 10 '14 at 15:20
  • The first part is incorrect, `@property NSString *firstName` isn't equivalent to `private String firstName` first of the java version is private and the objective-c version is default. – Popeye Jan 10 '14 at 15:28
  • The first part is incorrect,what your meaning? – wyf Jan 10 '14 at 15:35
  • When you do `@property NSString *firstName` in the `@interface` like you have it isn't private whereas in the java version you have actually marked it as private. – Popeye Jan 10 '14 at 15:39
  • I adopt your answer and i should learn more about Objective-c.Because I donot understand your comment . Very thanks again. – wyf Jan 10 '14 at 15:44

4 Answers4

5

Lets start with (2)

 @interface Person : NSObject
 {
 NSString *firstName;
 NSString *lastName;
 }
 @end

In this case firstName and lastName are know as ivars or Instance Variables for me I don't generally declare ivars. Some developers now say that you shouldn't put these in the @interface declaration for two reason.

  1. It exposes details about the implementation to users of the class, this will lead other developers who or using and in some cases yourself to rely on implementation details that should be available to them.

  2. Some developers believe that putting these in the @interface can make compile times significantly longer.

Most developers believe that the best way to implement an ivar is within the @implementation where braces are being used like:

@implementation Person {
    NSString *firstName;
    NSString *lastName;
}

The theory behind why we put them here is because theoretically they are declared private, preventing anyone from knowing about them except the developer who created the class. This will resolve all other developers from messing around with things they shouldn't.

The equivalent to this in Java is just as simple as private String firstName;


Now lets take a look at (1)

@interface Person : NSObject

@property NSString *firstName;
@property NSString *lastName;

@end

Technically @properties need only be used when the property needs to be accessible from other classes, but many developers prefer to use these over ivars as it makes them easier to use, and in new versions of xcode the ivars for these properties are declared automatically in the background.

By declaring a property you are basically automatically generating the getters and setters for these properties. In earlier versions of xcode you did have to @synthesize but there is no need for this anymore. So declaring the two properties firstName and lastName this will generate in the background

- (void)setFirstName:(NSString *)aFirstName
{
    self.firstName = aFirstName;
}

- (NSString *)firstName
{ 
    // Note in objective-c we don't generally use `get`
    return self.firstName;
}

- (void)setLastName:(NSString *)aLastName
{
    self.lastName= aLastName;
}

- (NSString *)lastName
{ 
    // Note in objective-c we don't generally use `get`
    return self.lastName;
}

When it comes to comparing this to Java this is near enough the same as

private String firstName;

public void setFirstName(String aFirstName) {
    this.firstName = aFirstName;
}

public String getFirstName() {
    return this.firstName;
}

We create out instance variable the same way we would do it as if it was a normal ivar but there is nothing to say create my setters and getters in java so we have to do that ourselves. Note that the ivar here in java is still private it is the getters and setters that we are opening up to others.


There is a sort of third option that you have missed as well. Due to the conventions in objective-c what would happen with a @property for a bool?

We have it declared like

 @property (nonatomic) BOOL personForObject; 

in objective-c when it comes to bools the getter is slightly different in name. Whilst we are happy with the synthesized setter of

- (void)setPersonForObject:(BOOL)aPersonForObject 
{
    self.personForObject = aPersonForObject;
}

we aren't happy though with the getter, when it comes to bools the getters should start with is so personForObjects getter should be isPersonForObject but the synthesize doesn't know this so will automatically generate the getter the other way. So we need to tell it in the property declaration like

@property (nonatomic, getter=isPersonForObject) BOOL personForObject;

You will now have to implement this method yourself though like

- (BOOL)isPersonForObject
{
    return self.personForObject;
}

Note this only need be done if you choice to ignore convention which I wouldn't recommend.

Any questions just ask.

Community
  • 1
  • 1
Popeye
  • 11,839
  • 9
  • 58
  • 91
  • Have some spinach. That was the best description. Kudos for calling out ivars in interface versus implementation. – uchuugaka Jan 10 '14 at 09:29
  • Little typo mate. You can't hold a `strong` reference to `BOOL` since it isn't an object. – Desdenova Jan 10 '14 at 09:42
  • @uchuugaka I actually ran out of time as I am in work but I was going to expand on how these would be called as well. – Popeye Jan 10 '14 at 10:42
  • I need cost some time to consume your answer, and if your answer is right, i will correct you! Thank your detail answer!Appreciate it! – wyf Jan 10 '14 at 12:19
  • Today, I take a lot time to study the Objective-C, and later i will ask some question on this topic.Thanks a lot. @Popeye – wyf Jan 10 '14 at 12:21
  • @Popeye Please review my answer beneath my question.Thanks a lot.^o^ – wyf Jan 10 '14 at 15:17
0

The code number two is equivalent to the Java version.

A @property in the most complete version defines the getter, setter and instance variable. You can also modify the declaration to specify only a getter, only a setter or to specify a different instance variable.

Francesco
  • 1,840
  • 19
  • 24
0

@property is shorthand for defining an instance variable and its corresponding accessors. If you just define instance variables in the interface, you will not get the accessor methods.

Fjölnir
  • 490
  • 2
  • 12
0

See whenever you declare members in objective-C you should provide getters and setters for those members(Variables). But Objective-C supports something called synthesized accessors using the directives @property and @synthesize.

Now lets see program with synthesized accessors :

#import<Foundation/Foundation.h>
@interface Person : NSObject{
NSString * firstName;// declaring that Person class as variable firstName
NSString * lastName;// // declaring that Person class as variable lastName
}

@property NSString *firstName; // says to compiler that we want to define synthesized accesor for the firstName
@property NSString *lastName;// says to compiler that we want to define synthesized accesor for the lastName
@end

@implementation Person

@synthesize firstName, lastName;// synthesized accessor to be defined for firstName and lastName

@end;

int main(){
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];
    Person * p = [[Person alloc]init] ;
    [p setFirstName:@"Yogish"]; // method setFirstName is implicitly defined by compiler
    [p setLastName:@"Gowda"];// method setLastName is implicitly defined by compiler
    NSLog(@"%@",p.firstName);
    NSLog(@"%@",p.lastName);
    [pool drain];
    return 0;

    }

Now coming back if u haven't used the @property and @synthesize you should have to write your own setters and getters method to set and get the members firstName and lastName. Since you're using @property and @synthesize the compiler will write getters and setter methods .

Hope this helps :)

iamyogish
  • 2,372
  • 2
  • 23
  • 40
  • You define firstName and lastName two times? or is just the same Variables – wyf Jan 10 '14 at 08:04
  • I am not defining the firstName and lastName two times. See the edited answer with the comments.. I – iamyogish Jan 10 '14 at 08:10
  • 2
    Most of the code is pretty outdated and therefore more confusing than helpful imo – Marc Jan 10 '14 at 08:16
  • @wyf Please go through this link you may get a better idea [Synthesized accesors](http://www.techotopia.com/index.php/Objective-C_-_Data_Encapsulation%2C_Synthesized_Accessors_and_Dot_Notation). :) – iamyogish Jan 10 '14 at 08:41
  • @iamyogish whilst yes it is correct it really is out of date, for your answer there is no need for the `ivars` or the `@synthesize` unless you're using a version of `xcode` that is ancient the `@synthesize` is done automatically for you, and same comes to the `ivars` these are now automatically created for properties. If you check the last modified at the bottom of the page for the link you have supplied it is almost 2 years out of date. Whilst it is correct and can be done that way still, it is also incorrect as there is really no point doing it that way. – Popeye Jan 10 '14 at 11:35