从超类调用子类的方法

Posted

技术标签:

【中文标题】从超类调用子类的方法【英文标题】:Call subclass's method from its superclass 【发布时间】:2011-11-22 20:31:16 【问题描述】:

我有两个类,分别命名为ParentChild,如下所示。 ParentChild 的超类我可以使用关键字super 从其子类中调用超类的方法。是否可以?

Child.h

#import <Foundation/Foundation.h>
#import "Parent.h"

@interface Child : Parent 



- (void) methodOfChild;

@end

Child.m

#import "Child.h"

@implementation Child

- (void) methodOfChild 

    NSLog(@"I'm child");



@end

Parent.h:

#import <Foundation/Foundation.h>

@interface Parent : NSObject 



- (void) methodOfParent;

@end

Parent.m:

#import "Parent.h"

@implementation Parent

- (void) methodOfParent 

    //How to call Child's methodOfChild here?



@end

在应用代理的 .m 文件头中导入“Parent.h”。

应用代理的application:didFinishLaunchingWithOptions: 方法..

Parent *parent = [ [Parent alloc] init];

[parent methodOfParent];

[parent release];

【问题讨论】:

是的,这在技术上是可行的,但这种设计有异味。特别糟糕。超类不应该知道它们的子类。 我想在从 swift 调用时实现相同的功能,swift 无法识别这种层次结构中的方法。当第一次从 swift 类初始化调用时,谁能告诉如何实现相同的目标? 【参考方案1】:

你可以,因为 Objective C 方法的调度都是动态的。只需使用[self methodOfChild] 调用它,这可能会生成编译器警告(您可以通过将self 转换为id 来使其静音)。

但是,看在上帝的份上,不要这样做。父母应该养活孩子,而不是孩子养父母。知道子类新方法的父级是一个巨大的设计问题,会在继承链上以错误的方式创建强耦合。如果父级需要它,为什么不是父级上的方法?

【讨论】:

可能发帖者正在考虑 C++ 风格的抽象基类(即定义方法但不提供实现的类),正确的建议是在父母,当且仅当相关时让孩子覆盖他们? 我们可以使用协议来做到这一点吗? 你可以,但你也可以将实现添加到父级,因为协议会声明你有(除非它是可选的,这有点……奇怪)。你想要这个设计用于什么情况?如果@Tommy 是对的,并且这是一个抽象基类代码,请按照他的建议执行并声明没有主体的方法,并让子代覆盖它。 是的,但没有任何好处。你也可以直接调用它。再次,我会问 - 为什么? 这个用例怎么样 - 如果你有多个类从父类继承,每个类都采用同名的方法并且不想在每个类中重新键入方法的调用孩子(多形体)?我想可以通过委托来完成,但使用 respondsToSelector 不仅更容易吗?【参考方案2】:

技术上你可以做到。但我建议你改变你的设计。您可以声明一个协议并让您的子类采用该协议。然后你可以检查孩子是否采用了超类的协议并调用超类的方法。

【讨论】:

您能否提供/分享一些示例代码以使用协议来实现?【参考方案3】:

你可以用这个:

Parent.m

#import "Parent.h"

@implementation Parent

- (void) methodOfChild 

    // this should be override by child classes
    NSAssert(NO, @"This is an abstract method and should be overridden");    


@end

父母知道孩子,孩子可以选择如何实现该功能。

【讨论】:

【参考方案4】:

super 表示“调用父类上的方法调度”,因此可以在子类中使用super,因为子类只有一个父类。一个类可以有很多 _sub_classes,那么在一般情况下,你怎么知道要调用哪个方法实现呢? (因此没有 sub 关键字之类的东西。)

但是,在您的示例中,您有两个单独的方法。没有什么能阻止你(假设你有非常好的理由做这样的事情!)在父母中说,

- (void) methodOfParent 
    [self methodOfChild];

【讨论】:

指出为什么答案不正确会很有帮助。碰巧,我的不是:obj-c 动态调度,super 的意思是“从我父母的方法字典开始执行方法查找”,你可能有一个很好的理由去做一些看起来不一样的事情太可怕了。【参考方案5】:

如果你的 super 有多个 subs,那么就选择这个特定的 sub的方法

if ([super isKindOfClass:[specificsub class]]) 
                [specificsub methodName];
            

如果你的 super 正在处理那个对象(那个 sub)那么 sub 的方法 登录将被称为另一种方式是在你的超类中

super *some = [[sub alloc] init];
[some methodName];

【讨论】:

【参考方案6】:

这可以通过覆盖子类中的方法来完成。那就是在父类中创建一个方法并在子类中覆盖相同的方法。

【讨论】:

以上是关于从超类调用子类的方法的主要内容,如果未能解决你的问题,请参考以下文章

Python子类方法从超类方法继承装饰器

无法从超类访问 Django 模型的子类

从超类中获取子类的名称

当子类使用Object变量实例化时,无法从超类访问方法

子类是不是从超类继承私有实例变量

从超类列表中提取给定子类的元素