如何防止方法被错误地覆盖

时间:2011-04-13 11:42:27

标签: objective-c methods override

如何防止方法在子类中被覆盖,错过了对其超类的实现的调用?。
我知道打电话[super methodName];有时会解决我的问题 但是,如果其他人要使用我的父类并覆盖我的方法,不小心失去了打电话给超级,我该怎么办?

更多解释:

我创建了一个具有方法-(void)indexDidChange:(int)index { }的viewcontroller VC1。我在那里写了一些我需要每次都要执行的操作。我将这个名为SVC1的viewcontroller子类化为其中我需要-(void)indexDidChange:(int)index { }来执行其他操作,但同时VC1 -(void)indexDidChange:(int)index { }操作也需要执行。所以我需要打个电话,

 -(void)indexDidChange:(int)index { 
[super indexDidChange:index];
}

所以我决定改变VC1的功能,如

  -(void)indexDidChange:(int)index {
     [self currentIndexDidChange:(int)index];
 }

-(void)currentIndexDidChange:(int)index { }

我需要 - (void)currentIndexDidChange:(int)index {}来覆盖和阻止 - (void)indexDidChange:(int)index {}来覆盖。

有可能吗?

3 个答案:

答案 0 :(得分:8)

编辑:在OP重新提出问题之后,很明显OP实际上并不是在寻找最终方法,尽管问题是初步措辞,这暗示了这一点。

OP关于方法覆盖安全的问题的新(更新)答案:

根据您的重新定义的问题,您并不是要保护方法完全不被覆盖,而是担心您的某个子类会覆盖某个方法,并且意外地忽略了在其新实现中包含对super的调用。

然而,这是一个相当普遍且普遍存在的问题,而且您每天都在处理这些问题,而不会过多关注它。

每个Objective-C程序员都熟悉以下方法,对吧?

- (void)dealloc {
    [iVar release], iVar = nil;
    [super dealloc]; //skipping this call to super is fatal!
}

我们知道跳过[super dealloc];会让事情变得不舒服。 (如果dealloc缺少对super的调用,那么clang编译器会发出警告,...非常方便。)

尽管这种方法的重写可能会导致致命的后果,但Apple并没有选择在此处设置任何类型的安全系统。

相反,Apple做了这个(与需要调用super的任何其他方法一样):

  • 在方法文档中添加注释:
  

After performing the class-specific deallocation, the subclass method should incorporate superclass versions of dealloc through a message to super

  • 期待你,程序员成为一名成年人,并对你的工作负责。并按照规则(由文档定义)进行播放。

请记住,- (void)dealloc绝不是例外。 Cocoa中有几十种这种类型的方法。 (以- (id)init的任何衍生物,大多数KVO观测方法等为例,仅举几例。)

所以你应该做的是:

  1. 为您写一份好的文档 方法即可。 (实际上,对整个项目更好
  2. 在方法的文档中添加一个大的响亮的注释,解释其规则。
  3. 在每个子类的重写方法实现上添加注释,在调用super的行的正上方,告诉读者/ dev查找文档,如果有疑问的话规则。 (可选)
  4. 负责任地编码。否则,你不应该在第一时间编码。最终你的客户会受到影响。

  5. 关于实现伪决赛方法的旧(预先改写)答案:

    您要求的是等同于最终函数,如Java或C ++所知。 与Java或C ++不同,Objective-C中没有最终方法

    根据您的情况,有一些解决方案可能使您至少接近您的目标你所能得到的只是稍微好一点的分离。您不会从中获得任何重要的安全性。在Objective-C中,您甚至无法确定方法的来源。 方法调整允许您随意交换方法。使用代码注入,您甚至可以在运行时将代码注入流程。所有这些都是Objective-C的设计。 Objective-C允许您锯掉您所坐的分支。因此,它要求你像成年人一样行事。因此,也没有私人方法。如果一个方法声称是私有的,那么你作为开发者应该有相应的行为。

    现在可能“ solutions ”:

    如果只有你的超级班级应该调用给定的(最终)方法:

    1. 然后 Macmade solution 使您的方法成为伪私有方法可以很好地运作。隐藏方法声明的缺点是,从子类调用隐藏方法会给你一个编译器警告,基本上阻止*(sic!)*你调用它。 (不会阻止你调用该方法。只会通过抛出编译器警告来避免你这样做。)
    2. 但是,如果要求子类调用给定(最终)方法:

      1. 使用delegation pattern,这样只会公开那些允许被覆盖的方法。
      2. 为防止覆盖,您可以使用class cluster& abstract factory模式,隐藏您的实现类,从而完全防止覆盖。 (Apple的NSArrayNSDictionaryNSSet类执行此操作)
      3. 但是你可能会注意到,由于Objective-C缺乏保护,通常只能在两者之间做出选择:开放性,保护性,不混合

答案 1 :(得分:4)

您可以在实现中使用类别,因此您的方法不会在头文件中公开。

MyClass.m

@interface MyClass( Private )

- ( void )myMethod;

@end

@implementation MyClass( Private )

- ( void )myMethod
{}

@end

@implementation MyClass

/* ... */

@end

答案 2 :(得分:0)

如果您没有在“.h文件”中声明您的功能,那么我认为它没有列出。