Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare an immutable property backed by a mutable type?

Tags:

I’d like to declare a public immutable property:

@interface Foo
@property(strong, readonly) NSSet *items;
@end

…backed with a mutable type in the implementation file:

@interface Foo (/* private interface*/)
@property(strong) NSMutableSet *items;
@end

@implementation
@synthesize items;
@end

What I want is a mutable collection in the implementation that gets cast into an immutable one when accessed from the outside. (I don’t care that the caller can cast the instance back to NSMutableSet and break the encapsulation. I live in a quiet, decent town where such things don’t happen.)

Right now my compiler treats the property as NSSet inside the implementation. I know there are many ways to get it working, for example with custom getters, but is there a way to do it simply with declared properties?

like image 511
zoul Avatar asked Oct 10 '11 08:10

zoul


3 Answers

The easiest solution is

@interface Foo {
@private
    NSMutableSet* _items;
}

@property (readonly) NSSet* items;

and then just

@synthesize items = _items;

inside your implementation file. Then you can access the mutable set through _items but the public interface will be an immutable set.

like image 170
edsko Avatar answered Nov 15 '22 11:11

edsko


You have to declare the property in the public interface as readonly in order the compiler not to complain. Like this:

Word.h

#import <Foundation/Foundation.h>

@interface Word : NSObject
@property (nonatomic, strong, readonly) NSArray *tags;
@end

Word.m

#import "Word.h"

@interface Word()
@property (nonatomic, strong) NSMutableArray *tags;
@end

@implementation Word
@end
like image 40
Mr. G Avatar answered Nov 15 '22 12:11

Mr. G


You could just do it yourself in your implementation:

@interface Foo : NSObject
    @property(nonatomic, retain) NSArray *anArray;
@end

--- implementation file ---

@interface Foo()
{
    NSMutableArray *_anArray;
}
@end

@implementation Foo

- (NSArray *)anArray
{
    return _anArray;
}

- (void)setAnArray:(NSArray *)inArray
{
     if ( _anArray == inArray )
     {
         return;
     }
     [_anArray release];
     _anArray = [inArray retain];
}

- (NSMutableArray *)mutablePrivateAnArray
{
    return _anArray;
}

@end
like image 23
D.C. Avatar answered Nov 15 '22 12:11

D.C.