【问题标题】:How can I prevent a method from being wrongly overridden如何防止方法被错误地覆盖
【发布时间】:2011-08-04 15:36:52
【问题描述】:

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

更多解释:

我创建了一个视图控制器 VC1,它有一个方法 -(void)indexDidChange:(int)index { }。我在那里写了一些我每次都需要执行的操作。我将这个名为 SVC1 的视图控制器子类化,我需要 -(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 { } 覆盖。

有可能吗?

【问题讨论】:

  • 您的问题不清楚。您似乎将 私有方法final 方法 的概念混为一谈。您是要防止调用类的子类中的方法,还是要防止覆盖类的子类中的方法?这是完全不同的两件事。
  • @Regexident,现在清楚了吗?有希望吗?谢谢回复....
  • 好的,谢谢。因此,显然与您原来的措辞相反,您根本没有寻找最终方法。我相应地更新了我的答案。

标签: objective-c methods overriding


【解决方案1】:

编辑:在 OP 重新表述问题后,很明显 OP 实际上并不是在寻找 final methods,尽管问题的初始表述只是暗示了这一点。

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

根据您重新表述的问题,您根本不是在寻求保护方法不被覆盖,而是担心您的一个子类会覆盖方法并意外丢失以在其新实现中包含对 super 的调用。

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

每个Objective-C程序员都熟悉下面的方法吧?

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

我们都知道跳过[super dealloc]; 会让事情变得不舒服。 (afaik 如果 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 的行上方,告诉读者/开发人员在对规则有疑问时查找文档。 (可选)
  4. 负责任地编写代码。否则,您不应该首先编写代码。最终会受到影响的是您的客户。

关于归档伪最终方法的旧(重新表述)答案:

您所要求的是与 Java 或 C++ 中已知的 final 函数 等效的内容。 与 Java 或 C++ 不同,Objective-C 中没有 final 方法

根据您的情况,有一些解决方案可能让您至少接近您的目标您将获得的只是更好的分离效果。您不会从他们那里获得任何重要的安全性。在 Objective-C 中,您甚至无法确定方法的来源。 方法调配允许您随意交换方法。通过代码注入,您甚至可以在运行时将代码注入进程。这一切都是由 Objective-C 设计的。 Objective-C 允许你锯掉你所在的分支。因此,它要求你表现得像个成年人。因此也没有私有方法。如果一个方法被宣布为私有的,那么作为开发人员的你应该有相应的行为。

现在到可能的“解决方案”:

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

  1. 然后Macmadesolution 将您的方法设为伪私有方法 会很有效。隐藏方法声明的缺点是,从子类调用隐藏方法会给你一个编译器警告,基本上阻止*(原文如此!)*你调用它。 (但它不会阻止您调用该方法。它只会通过抛出编译器警告来避免您这样做。)

如果期望子类调用给定的(最终)方法:

  1. 使用delegation pattern,这样只会公开那些允许被覆盖的方法。
  2. 为了完全防止覆盖,您可以使用class clusterabstract factory 模式,这会隐藏您的实现类,从而完全防止覆盖。 (Apple 的 NSArrayNSDictionaryNSSet 类就是这样做的)

但是您可能会注意到,由于 Objective-C 缺乏保护,通常只能在两者之间进行选择:开放性、保护性、不能混合使用

【讨论】:

【解决方案2】:

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

MyClass.m

@interface MyClass( Private )

- ( void )myMethod;

@end

@implementation MyClass( Private )

- ( void )myMethod
{}

@end

@implementation MyClass

/* ... */

@end
【解决方案3】:

如果您没有在“.h 文件”中声明您的函数,那么我认为它不会被列出。

【讨论】:

  • @NaveenShan 它在哪里说什么?
猜你喜欢
  • 2017-12-19
  • 2021-02-08
  • 2020-07-23
  • 1970-01-01
  • 2018-09-11
  • 2018-06-27
  • 1970-01-01
  • 2011-05-26
  • 2017-08-27
相关资源
最近更新 更多