Objective c 目标C-常数与行为

Objective c 目标C-常数与行为,objective-c,cocoa,Objective C,Cocoa,我不熟悉Objective C。我正在尝试定义与它们相关的行为的常量。到目前为止,我已经做了- @interface Direction : NSObject { NSString *displayName; } -(id)initWithDisplayName:(NSString *)aName; -(id)left; // returns West when North -(id)right; // return East when North @end @impleme

我不熟悉Objective C。我正在尝试定义与它们相关的行为的常量。到目前为止,我已经做了-

@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"]; // error - initializer element is not constant.

这种方法会导致指示的错误。在目标C中是否有更好的方法来实现这一点。

简短版本

存储方向的几何表示(使用矢量或简单角度),并动态计算方向名称。要获得左右方向,复制向量并旋转±½π或±90°,创建新方向并返回该方向。如果只有90°转弯,则可以使用点{0,1},并切换方向,也可以在执行此操作时取消方向。({0,1}是北;{1,0}是东,{-1,-0}是西,{-0,-1}是南,所以如果使用这种方法,您必须有一些额外的代码来确定何时求反,何时不求反。)

长版本

问题是函数之外的变量是在编译时初始化的。当然,这意味着您不能调用函数来初始化它们。要执行类似操作,您需要执行以下操作(尽管您不应该这样做,请参见下文):

然而,这是一种几乎完全可怕的做事方式。您要做的如下操作:

// 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.
}
这将防止该方向的其他用户(大部分)做坏事

PS:North是一个非常奇怪的词,当你经常键入它时,它尤其引人注目P

编辑:关于将基本方向用作单独对象的一些说明

在实践中,您的指导课程可能如下所示:

@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

短版

存储方向的几何表示(使用矢量或简单角度),并动态计算方向名称。要获得左右方向,复制向量并旋转±½π或±90°,创建新方向并返回该方向。如果只有90°转弯,则可以使用点{0,1},并切换方向,也可以在执行此操作时取消方向。({0,1}是北;{1,0}是东,{-1,-0}是西,{-0,-1}是南,所以如果使用这种方法,您必须有一些额外的代码来确定何时求反,何时不求反。)

长版本

问题是函数之外的变量是在编译时初始化的。当然,这意味着您不能调用函数来初始化它们。要执行类似操作,您需要执行以下操作(尽管您不应该这样做,请参见下文):

然而,这是一种几乎完全可怕的做事方式。您要做的如下操作:

// 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.
}
这将防止该方向的其他用户(大部分)做坏事

PS:North是一个非常奇怪的词,当你经常键入它时,它尤其引人注目P

编辑:关于将基本方向用作单独对象的一些说明

在实践中,您的指导课程可能如下所示:

@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

这里的想法也是为了每个方向封装相应的行为,即左、右(上面的例子)。如果每个方向都是ConstantDirection的一个实例,那怎么可能呢?
ConstantDirection
的其他子类(或者直接是
Direction
)<代码>北:方向。不过,同样,这是一种几乎完全糟糕的方式,将answer.initialise northDirection更新为nil,而不是NULL/学究式的。@JeremyP:嗯,这看起来确实太学究式了。就我个人而言,我总是专门使用
NULL
;不太清楚为什么。一定是在苹果上看到的™ 某处的品牌示例代码(snort)。而且,不是真的。这里需要的不是
(struct objc_class*)NULL
nil
);它实际上是
(Direction*)NULL
。我觉得
NULL
是合适的。不同意。方向是对Objective-C对象的引用,因此在这里使用nil是合适的。我知道这实际上没有什么区别(尽管苹果列表上关于NULL是否真的是0的冗长乏味的讨论),但我更喜欢Objective-C方法。这里的想法也是为了每个方向封装相应的行为,即左、右(上面的例子)。如果每个方向都是ConstantDirection的一个实例,那怎么可能呢?
ConstantDirection
的其他子类(或者直接是
Direction
)<代码>北:方向。不过,同样,这是一种几乎完全糟糕的方式,将answer.initialise northDirection更新为nil,而不是NULL/学究式的。@JeremyP:嗯,这看起来确实太学究式了。就我个人而言,我总是专门使用
NULL
;不太清楚为什么。一定是在苹果上看到的™ 某处的品牌示例代码(snort)。而且,不是真的。这里需要的不是
(struct objc_class*)NULL
nil
);它实际上是
(Direction*)NULL
。我觉得
NULL
是合适的。不同意。方向是对Objective-C对象的引用,因此在这里使用nil是合适的。我知道这实际上没有什么区别(尽管苹果列表上关于NULL是否真的是0的冗长乏味的讨论),但我更喜欢Objective-C方式。