Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I create properties with a public getter and private setter?

I'd like to use properties for my instance variables, but in many cases, I only want the class itself to have access to the setter. I was hoping I could do something like this:

Foo.h:

@interface Foo {
  NSString *bar;
}
@property (readonly) NSString *bar;
@end

Foo.m:

#import "Foo.h"

@interface Foo ()
@property (copy) NSString *bar;
@end

@implementation Foo
@synthesize bar;
@end

But this generates a warning:

Foo.m:4: warning: property ‘bar’ attribute in ‘Foo’ class continuation does not match class ‘Foo’ property

I can see what it's complaining about, but it still seems like a useful idiom. Is there some other way to accomplish this without writing my own setters?

like image 966
Mark Smith Avatar asked May 05 '09 22:05

Mark Smith


People also ask

Can getters and setters be private?

The reason for declaring the getters and setters private is to make the corresponding part of the object's abstract state (i.e. the values) private. That's largely independent of the decision to use getters and setters or not to hide the implementation types, prevent direct access, etc.

Should getters and setters be public or private?

Usually you want setters/getters to be public, because that's what they are for: giving access to data, you don't want to give others direct access to because you don't want them to mess with your implementation dependent details - that's what encapsulation is about.

What is the benefit of using properties with getters and setters?

The getter and setter method gives you centralized control of how a certain field is initialized and provided to the client, which makes it much easier to verify and debug. To see which thread is accessing and what values are going out, you can easily place breakpoints or a print statement.

Do getters and setters permit different access levels?

Allowing the getter/setter to be passed around as lambda expressions rather than values. Getters and setters can allow different access levels - for example the get may be public, but the set could be protected.


2 Answers

Your approach is correct, but the redeclaration of @property bar in the class extension must match the original declaration except for readwrite vs. readonly. So this will work:

Foo.h

@interface Foo {
  NSString *bar;
}
@property (copy,readonly) NSString *bar;
@end

Foo.m:

#import "Foo.h"

@interface Foo ()
@property (copy,readwrite) NSString *bar;
@end

@implementation Foo
@synthesize bar;
@end

(recall that the default is assign for properties, not copy).

like image 106
Barry Wark Avatar answered Nov 04 '22 20:11

Barry Wark


When Barry says "the default is retain for properties" he means that retain should be specified like this:

@property (retain) NSDate *endDate;

If they are left like this:

@property NSDate *endDate;

assign is assumed by the compiler.

like image 21
David Weiss Avatar answered Nov 04 '22 21:11

David Weiss