上拉重构,Objective-C

时间:2009-12-08 12:59:24

标签: objective-c refactoring design-patterns

我有两个类似的课程MultiSlotBlockSingleSlotBlock。他们已经开始分享很多常用代码,所以我决定做一些重构并将一些方法拉到一个新的超类,让我们称之为Block

现在我提出的一个方法,简化了示例,如下所示:

// (Block.mm)

- (void)doACommonBehaviour
{       
      // .. does some stuff

      [self doAUniqueBehaviour];
}

这里的问题是[self doAUniqueBehaviour]显示警告,因为我的超类当然没有在任何地方实现此方法。

我想到的两个解决方案对我来说听起来不太好。一种是使用协议(我目前的方式),如下所示:

// (Block.mm)

- (void)doACommonBehaviour
{       
      // .. does some stuff

      if ([self conformsToProtocol:@protocol(UniqueBehaviourProtocol)])
      {
           id<UniqueBehaviourProtocol> block = (id<UniqueBehaviourProtocol>)self;
           [block doAUniqueBehaviour];
      }
}

另一个是在我的超类中有一个空白的方法体(在这种情况下会有很多)并且只返回doesNotRespondToSelector

我脑后想到的是我应该使用策略模式,但我可能会离开,而我还没有想过如何实现它。

有什么想法吗?感谢。

编辑:我知道doAUniqueBehaviour将在所有子类中实现的事实,它只是不同的实现。

3 个答案:

答案 0 :(得分:3)

超类不应该知道它的子类。你应该实现 每个子类中的- (void)doACommonBehaviour方法都在那里:

- (void)doACommonBehaviour
{     
      [super doACommonBehaviour];
      [self doAUniqueBehaviour];
}

编辑 - 澄清:

如果所有子类都要实现-doAUniqueBehaviour,那么它应该在超类中实现(甚至是空),每个子类都会根据需要覆盖它。

如果subclass1实现-doAUniqueBehaviour1,则子类2实现-doAUniqueBehaviour2等,然后执行我上面提出的建议;例如。在subclass1:

- (void)doACommonBehaviour
{     
      [super doACommonBehaviour];
      [self doAUniqueBehaviour1];
}

答案 1 :(得分:2)

Objective-C中没有抽象类这样的概念。为了避免警告,您必须在基类中提供默认实现。通常,此实现将在运行时抛出doesNotRespondToSelector错误:

- (id)someMethod:(SomeObject*)blah 
     [self doesNotRecognizeSelector:_cmd];
     return nil;
}

注意:_cmd参数是被调用的选择器。

答案 2 :(得分:1)

@Dimitri的建议可行,但不是强制每个子类实现相同的方法,你可以在Block中声明它一次,并且在该方法之上(在实现文件中,而不是头文件)声明这样的唯一方法:

- (void) doUniqueBehaviour { }

- (void) doCommonBehaviour {     
    // any common code you need
    [self doUniqueBehaviour];
}

这将阻止任何编译器警告,您可以根据需要覆盖子类中的-doUniqueBehaviour。它还避免了代码重复,并减少了在一个子类而不是另一个子类中更改代码的可能性。此外,您不需要单独的协议,并保留动态类型。