开发者

Objective C - Constants with behaviour

开发者 https://www.devze.com 2022-12-31 01:10 出处:网络
I\'m new to Objective C. I am trying to define Constants which have behavior associated with them. So far I have done -

I'm new to Objective C. I am trying to define Constants which have behavior associated with them. So far I have done -

@interface Direction : NSObject {
     NSString *displayName;
}

-(id)initWithDisplayName:(NSString *)aName;

-(id)left; // returns West when North

-(id)right; // return East when North

@end

@implementation Direction

    -(id)initWithDisplayName:(NSString *)aName
    {
        if(self = [super init])
        {
            displayName = aName;
        }   
        return self;
    }

    -(id)left {};
    -(id)right {};

@end

Direction* North = [Direction initWithDisplayName:@"North"]; // err开发者_高级运维or - initializer element is not constant.

This approach results in the indicated error. Is there a better way of doing this in Objective C.


Short version

Store a geometric representation of your direction (using a vector or a simple angle) and compute the direction names dynamically. To get left and right directions, copy and rotate your vector by ±½π or ±90°, creating a new direction and returning that. If you only have 90° turns, you can use a point { 0, 1 }, and switch the directions, optionally negating them as you do so. ({ 0, 1 } is North; { 1, 0 } is East, { -1, -0 } is West, { -0, -1 } is South, so if you use this approach you'll have to have some extra code to determine when to negate, and when not to.)

Long version

The issue is that variables outside of functions are initialized at compile time. Naturally, this means that you cannot call functions to initialize them. To do something like this, you need to do the following (although you shouldn't, see below):

// Direction.h

extern Direction *north;

// Direction.m

Direction *north = nil;

+ (void)initialize {
  north = [[Direction alloc] initWithDisplayName:@"North"];
}

This is, however, an almost entirely terrible way of going about things. What you want to do is as follows:

// Direction.h


@interface Direction (ConstantDirections)

+ (Direction *)north;
// etc...

@end

// Direction.m

+ (Direction *)north {
  static Direction *northDirection = nil;
  if (!northDirection) {
    // assume that ConstantDirection is a subclass of
    // Direction that prevents releases etc.
    northDirection = [[ConstantDirection alloc] initWithDisplayName:@"North"];
  }
  return northDirection.
}

This will prevent other users of the direction from doing evil things (mostly).

PS: North is a really weird word, especially noticeable when you type it a lot. :P

Edit: Some clarification on the use of cardinal directions as separate objects.

In practice, your direction class will probably look something like this:

@interface Direction : NSObject <NSCopying,NSCoding> {
  NSString *displayName;

  NSPoint offset;
  // XOR
  NSInteger northOffset;
  NSInteger eastOffset;
  // XOR
  CGFloat theta;
}

@property (copy) NSString *displayName;
@property (readonly) NSPoint offset;

+ (Direction *)north;
+ (Direction *)east;
+ (Direction *)west;
+ (Direction *)south;

- (id)initWithOffset:(NSPoint)offset;

@end

For the purpose of this discussion, we'll assume the first.

In this case, your Direction.m file would contain, among other things, the following.

@implementation Direction 

+ (Direction *)north {
  static Direction *northDirection = nil;
  if (!northDirection) {
    // assume that ConstantDirection is a subclass of
    // Direction that prevents releases etc.
    northDirection = [[ConstantDirection alloc] initWithOffset:NSMakePoint(0,DIRECTION_LARGE_OFFSET)];
    northDirection.displayName = @"North";
  }
  return northDirection.
}

@end
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号