3

I want to make a readonly instance of a class in Objective C. I have a vector class which is basically floats for x and y position and some methods. In a lot of cases I need a (0, 0)-vector so I was thinking instead of allocating a new one each time that I would have a shared zero vector, something like this:

// Don't want to do this all the time (allocate new vector)
compare(v, [[Vector alloc] initWithCartesian:0:0]);

// Want to do this instead (use a shared vector, only allocate once)
compare(v, [Vector zeroVector]);

// My attempt so far
+ (Vector *)zeroVector {
    static Vector *sharedZeroVector = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedZeroVector = [[self alloc] initWithCartesian:0:0];
    });
    return sharedZeroVector;
}

// The problem
v.x = 3;

This works fine, except that the zero vector is not readonly, which feels kind of silly. As a note I would like to mention that this is more of a want-to-know-how-to kind of question than an actual problem, I don't know if it will make some actual difference.

Reason
  • 1,410
  • 12
  • 33
  • What do you mean by "it's not readonly"? FYI as currently stands, you **cannot** do `[Vector setZeroVector:foo];`, since that's not implemented. –  Apr 17 '13 at 14:37
  • a simpler workaround: you could create a -(BOOL)isZero method in your vector class and there check for the coord properties, like if (self.x==0 &&...). This don't answer your question but may be a cleaner and faster solution to your problem :) – il Malvagio Dottor Prosciutto Apr 17 '13 at 15:34

3 Answers3

5

The common solution is having all instances immutable (see NSNumber, NSDecimalNumber etc.), possibly having a second mutable class (NSString vs NSMutableString or NSArray vs NSMutableArray).

Sulthan
  • 128,090
  • 22
  • 218
  • 270
4

Depends on how your standard vector should work. If you never want to set x and y via property you could just make them readonly:

@property (nonatomic, readonly) NSInteger x;
@property (nonatomic, readonly) NSInteger y;

If some of your vectors should be readwrite you can create a readonly class Vector and derive a class MutableVector:

@interface Vector : NSObject
  @property (nonatomic, readonly) NSInteger x;
  @property (nonatomic, readonly) NSInteger y;
@end

@interface MutableVector : Vector
  @property (nonatomic) NSInteger x;
  @property (nonatomic) NSInteger y;
@end

You would then use Vector for zeroVector and MutableVector for all others.

lassej
  • 6,256
  • 6
  • 26
  • 34
0

Do you just want to prevent other classes from changing this class fields?

Mark them as @private and (as Sulthan writes), make sure the class that your -zeroVector method returns is immutable (perhaps an immutable subclass of Vector), i.e. there are no methods that would allow other code to change it's state.

See also a related question about Obj-C private fields.

Community
  • 1
  • 1
david a.
  • 5,283
  • 22
  • 24