【问题标题】:Calling method on child class from parent class method (Objective-c 2.0)从父类方法调用子类的方法(Objective-c 2.0)
【发布时间】:2012-01-21 13:50:57
【问题描述】:

我有面向对象编程的经验,但是由于某种原因,这种情况并不熟悉。考虑以下 Objective-c 2.0 代码:

@interface A : NSObject
@end

@implementation A
- (void) f {
    [self g];
}
@end

@interface B : A
@end

@implementation B
- (void) g {
    NSLog(@"called g...");
}
@end

这是从父类中的方法调用子类方法的正确方法吗?如果另一个子类没有实现方法g,会发生什么?也许有更好的方法来解决这个问题,比如父类A中的抽象方法?

【问题讨论】:

标签: objective-c inheritance methods


【解决方案1】:

关键是在父类中有一个可以在子类中被覆盖的方法。

@interface Dog : NSObject
- (void) bark;
@end

@implementation Dog
- (void) bark {
    NSLog(@"Ruff!");
}
@end

@interface Chihuahua : Dog
@end

@implementation Chihuahua
- (void) bark {
    NSLog(@"Yipe! Yipe! Yipe!");
}
@end

你看,你的子类会用它自己的实现覆盖父方法。你可能会看到它是这样使用的:

Dog *someDog = [Chihuahua alloc] init] autorelease];
[someDog bark];

输出:Yipe! Yipe! Yipe!

【讨论】:

  • 有道理。 bark是否需要在父类接口中声明?
  • bark 应该在你的界面中声明。是的。
  • 在不同的情况下,您确实希望调用不同的方法,例如您所描述的方法。例如,您可能想要使用模板模式:template method pattern,就像在我的示例中一样,如果您想调用 bark,但是,bark 会依次调用一些内部方法,然后这些方法将被子类覆盖,有点像 Squeegy 的例子。
【解决方案2】:

你应该在父类中实现g,但让它什么都不做。这样可以正确调用它,但仍然可以被覆盖。

@interface A : NSObject
@end

@implementation A
- (void) f {
    [self g];
}
- (void) g {} // Does nothing in baseclass
@end

@interface B : A
@end

@implementation B
- (void) g {
    NSLog(@"called g...");
}
@end

或者你在执行之前检查对象上的方法。

if ([self respondsToSelector:@selector(g)]) {
  [self performSelector:@selector(g) withObject:nil];
}

但这可能会变得很丑。

【讨论】:

  • 编译器会发出警告,不是吗?既然编译认为它知道self的类没有实现那个方法?
猜你喜欢
  • 2016-02-14
  • 2017-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-21
  • 1970-01-01
  • 2012-02-09
  • 2012-02-22
相关资源
最近更新 更多