【问题标题】:Manipulating properties in init that are set up by a sub-class in Objective-C在init中操作由Objective-C中的子类设置的属性
【发布时间】:2013-12-20 10:47:25
【问题描述】:

我在 Objective-C 中有一个抽象接口,其中每个子类都需要设置一个属性,然后在 init 末尾对该属性执行完全相同的操作。我试图避免使用类似这样的重复代码:

接口文件

@interface Shape : NSObject

@property (nonatomic) PropertyType *prop;

- (id)init;
- (void)initProperty;

@end

实施文件

@implementation Shape

- (id)init
{
    if(self = [super init]) {
        [self initProperty];
        [prop doSomething];
    }
    return self;
}

- (void)initProperty
{
}

@end

我的问题是每个子类都需要一组不同的参数传递给initProperty,以便正确实现该方法:

@implementation Rectangle

- (void)initPropertyWithRect:(CGRect)rect
{
    prop = [RectangleStuff rectangleWithRect:rect];
}

@end

@implementation Circle

- (void)initPropertyWithRadius:(CGFloat)radius
{
    prop = [CircleStuff circleWithRadius:radius];
}

@end

有没有一种干净的方法来做我在 Objective-C 中尝试做的事情?到目前为止,我的选择似乎是:

  1. 创建一个“财产包”,然后传递一个NSDictionary
  2. 在每个子类中复制 [property doSomething]; 代码。
  3. 不知何故将工厂对象传递给init,并让工厂对象创建prop。这种方法似乎最干净,但我需要工厂对象以某种方式将矩形和/或半径保持为内部状态,这对我来说似乎并不干净。

有什么想法吗?

【问题讨论】:

  • 顺便说一下,不要使用 init 来作为这些方法名称。如您所见:clang.llvm.org/docs/… init 系列中的方法隐式使用它们的 self 参数并返回一个保留对象。
  • @GabrielePetronella 谢谢你的提醒......我一直在犯这个错误。

标签: ios objective-c initialization factory template-method-pattern


【解决方案1】:

我可能会选择#2(为了简单起见)。如果属性只设置一次 (在子类 init 方法中),您可以覆盖 超类,并在那里做额外的事情。

未经测试的代码:

- (void)setProp:(PropertyType *)prop
{
    _prop = prop; // (Assuming ARC)
    [_prop doSomething];
}

【讨论】:

    【解决方案2】:

    首先,我觉得有必要提一下,除了初始化对象之外,您的 init 函数不应该做任何事情。也就是说,每条规则都有打破的时间和地点,所以我会提供我能提供的建议。

    您的 init 函数与任何其他函数没有什么不同。您可以在调用 super 之前和之后执行操作。虽然通常不鼓励,但这将是一个很好的地方。您的子类中的 init 现在看起来像这样:

    - (id)init
    {
        self.myProperty = value;
        self = [super init];
        if (self) {
            // more init stuff
        }
        return self;
    }
    

    【讨论】:

      【解决方案3】:

      我最终使用了其他两个答案中建议的变体:

      Shape.h

      @interface Shape : NSObject
      
      @property (nonatomic) PropertyType *prop;
      
      - (id)initWithProperty:(PropertyType *prop);
      
      @end
      

      Shape.m

      @implementation Shape
      
      - (id)initWithProperty:(PropertyType *)prop
      {
          if(self = [super init]) {
              _prop = prop;
              [_prop doSomething];
          }
          return self;
      }
      
      @end
      

      Rectangle.m/Circle.m

      @implementation Rectangle
      
      - (void)initWithRect:(CGRect)rect
      {
          return [self initWithProperty:[RectangleStuff rectangleWithRect:rect]];
      }
      
      @end
      
      @implementation Circle
      
      - (void)initWithRadius:(CGFloat)radius
      {
          return [self initWithProperty:[CircleStuff circleWithRadius:radius]];
      }
      
      @end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-09
        • 2011-12-16
        • 1970-01-01
        • 1970-01-01
        • 2016-04-02
        相关资源
        最近更新 更多