【问题标题】:Adding a custom initWith?添加自定义 initWith?
【发布时间】:2018-06-14 07:11:29
【问题描述】:

如果我为一个对象创建一个自定义 initWith,我是否本质上包含了我想要覆盖 init 时要添加的代码?

-(id) init {
    self = [super init];
    if (self) {
        NSLog(@"_init: %@", self);
    }
    return(self);
}

例如

-(id) initWithX:(int) inPosX andY:(int) inPosY {
    self = [super init];
    if(self) {
        NSLog(@"_init: %@", self);
        posX = inPosX;
        posY = inPosY;
    }
    return(self);
}

加里

【问题讨论】:

    标签: objective-c


    【解决方案1】:

    您可以创建一个指定初始化程序,它接受您希望在初始化时提供的所有参数。

    然后你从你的另一个 -(id)init 调用你指定的初始化器并使用适当的参数。

    只有指定的初始化器才会初始化超类[super init]

    例子:

    - (id)init
    {
        return [self initWithX:defaultX andY:defaultY];
    }
    
    - (id)initWithPosition:(NSPoint)position
    {
        return [self initWithX:position.x andY:position.y];
    }
    
    
    - (id)initWithX:(int)inPosX andY:(int)inPosY
    {
        self = [super init];
        if(self) {
            NSLog(@"_init: %@", self);
            posX = inPosX;
            posY = inPosY;
        }
        return self;
    }
    

    指定的初始化程序是-(id)initWithX:andY:,您可以从其他初始化程序调用它。

    如果你想扩展这个类,你可以从子类中调用你指定的初始化器。

    【讨论】:

    • return(self); 行的 self 周围的括号是什么原因?它是否返回 BOOL 值?
    【解决方案2】:

    我建议创建一个主初始化程序来处理大部分工作。然后,您可以创建任意数量的其他初始化器,它们都调用这个主初始化器。这样做的好处是如果你想改变初始化过程,你只需要改变一个点。它可能看起来像这样:

    -(id) initWithX:(float)x {
        if (self = [super init]) {
            /* do most of initialization */
            self.xVal = x;
        }
        return self;
    }
    
    -(id) init {
        return [self initWithX:0.0f];
    }
    

    在这个例子中,initWithX: 是我们的主要初始化器。另一个初始化程序 (init) 只需调用 initWithX: 并使用默认值(在本例中为 0)。

    【讨论】:

    • 你的init应该返回[self initWithX:0.0f]的结果。
    • 是的,错过了。固定的。谢谢。
    【解决方案3】:

    是的,我就是这样做的。稍作改动就会删掉一行代码:

     if (self = [super init]) {
    

    相对于:

     self = [super init];
     if(self) {
    

    【讨论】:

    • 启用警告的 GCC 会抱怨,因为 if 中的 = 更常见于意外而不是故意使用。我会按照 OP 现在的方式编写它,但要使警告静音,if ((self = [super init]))(请注意额外的括号)会这样做。
    • 所以你想将相同的初始化代码复制到你为这个非常复杂的类所拥有的所有 150 种不同的初始化方法中?
    • 不,stefan,我通常会按照您的方式行事。我阅读他的示例的方式是将init:更改为initWithX:andY:,而不是添加initWithX:andY:,所以没有进入这方面。但这是一个很好的观点,很高兴你做到了!谢谢,ehemient,你的评论。我一直想知道为什么代码示例经常这样做,因为没有它它构建得很好。显然在我的 XCode 中并没有启用所有警告。你启发了我!
    【解决方案4】:

    对于modern Objective-C ...

    UDFile.h

    #import <Foundation/Foundation.h>
    
    @interface UDFile : NSObject
    
    @property (nonatomic, strong) NSString *name;
    
    - (instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER;
    
    @end
    

    UDFile.m

    #import "UDFile.h"
    
    @implementation UDFile
    
    - (instancetype)initWithName:(NSString *)name {
        self = [super init];
        if (self) {
            _name = [name copy];
        }
        return self;
    }
    
    - (instancetype)init {
        return [self initWithPathname:@""];
    }
    

    【讨论】:

      【解决方案5】:

      有时,您希望重用一些初始化代码并仅针对特定初始化程序稍微修改其行为。在这种情况下,我执行以下操作:

      
      - (id) init
      {
          self = [super init];
          if (!self) return nil;
      
          // These values are always initialised this way
          ivar1 = 10;
          ivar2 = @"HellO";
          ivar3 = [[NSMutableArray alloc] initWithCapacity:10];
          ivar4 = 22;
      
          return self;
      }
      
      - (id) initWithIvar4:(int) aValue
      {
          // call -init on self, which will call -init on super for us, and set
          // up ivar1, ivar2, ivar3, and ivar4.
          self = [self init];
          if (!self) return nil;
      
          // Change ivar4 from the default 22 to whatever aValue is.
          ivar4 = aValue;
      
          return self;
      }
      
      

      【讨论】:

      • 这是另一种选择,但如果您只调用 init 最终会导致 ivar4 未初始化,您必须记住,在该特定初始化程序中,您不会初始化某些变量,而是初始化其他初始化程序初始化它们...听起来有点太容易出错了...
      • 对不起,我没有提供一个很好的例子。此代码旨在接受 ivar4 的默认值为 0,除非专门使用 initWithIvar4: 设置。你也可以很容易地在-[self init] 中设置ivar4,但你是对的,你可以很容易地以初始化一些变量而结束一些变量,并且不容易追踪某些变量的设置位置。
      猜你喜欢
      • 2012-12-09
      • 2021-12-29
      • 2020-03-22
      • 1970-01-01
      • 2017-11-01
      • 2012-07-10
      • 2018-10-30
      • 2021-04-12
      • 2020-07-07
      相关资源
      最近更新 更多