为什么在允许的情况下覆盖@interface中的ivar是允许的,但有这种奇怪的行为?

时间:2014-05-30 17:35:10

标签: ios objective-c inheritance override ivar

我只是对这个问题感到好奇,我发现这个解决方案绝对错误,所以我没有使用它,但是因为它错误地发生在我身上(这是一个让我花费数小时调试的错字)现在我发布了在这里提出一个问题,找出为什么会发生这一切的答案。

我有三个班级:

SharedObject 类,这是一个不做任何事情的愚蠢的类......或者,做的事情

// .h file
@interface SharedObject : NSObject

- (void) doStuff;

@end

// .m file
#import "SharedObject.h"

@implementation SharedObject

- (void) doStuff{

    NSLog(@"doin' stuff");
}

@end

超类类声明了一个 SharedObject 类的ivar,以及两个方法,一个只是应该(但不是)init对象,另一个使用对象:

// .h file
#import "SharedObject.h"

@interface Superclass : NSObject{
    SharedObject *_sharedObj;
}

- (void) initSharedObject;
- (void) useSharedObject;

@end

// .m file
#import "Superclass.h"

@implementation Superclass

- (void) initSharedObject{
    ;;
}

- (void) useSharedObject{

    [_sharedObj doStuff];
}
@end
子类类,超类的子类(对于命名混乱!),它实际上实现了initSharedObject方法并且在 sharedObject ;然而,这个子类有一个隐藏的类别(这里是没有给出编译错误的混乱),其中 SharedObject ivar被完全相同的名称覆盖:

// .h file
#import "Superclass.h"

@interface Subclass : Superclass{

}
@end 

// .m file
#import "Subclass.h"

@interface Subclass (){
    //here's where the mess takes place
    SharedObject *_sharedObj;
}

@end

@implementation Subclass

- (void) initSharedObject{

    [super initSharedObject];

    //this class inits the shared object here.
    _sharedObj = [SharedObject new];

}
@end

现在,尽管我已经意识到这里写的内容只是错误,但我问自己为什么我会得到这种奇怪的行为;如果实例化子类并在其上调用initSharedObjectuseSharedObject,请执行以下操作:

Subclass *test = [Subclass new];
[test initSharedObject];
[test useSharedObject];

没有任何反应,我的意思是绝对没有,当然没有编译错误/警告,但是没有执行错误,方法调用被忽略,任何事情都会发生;如果我在子类中移动useSharedObject方法实现,我有正确的登录控制台。 我想知道在运行时,当我错误地覆盖Ivar时会发生什么。任何猜测我都感觉很臭,所以我想知道是否有人对该场景中的编译工作方式以及为什么不调用日志有一个准确而正确的答案。

2 个答案:

答案 0 :(得分:2)

该方法不会被忽略。发生的事情是你有两个对象,我将它们称为superSharedObject和sharedObject。

运行initSharedObject时,您将实例化sharedObject。然后在Subclass上调用useSharedObject(它没有实现useSharedObject)时,运行SuperClass的useSharedObject实现。该实现使用superSharedObject,而不是sharedObject。在objective-c中调用未初始化(nil)对象上的方法不会给你一个错误。如果方法有输出,它将什么都不做或返回nil。这是设计的。

答案 1 :(得分:2)

缺少编译器诊断是一个错误。编译器应该能够看到重复的ivars和抱怨。您应该在http://bugreport.apple.com提交错误报告。

运行时的行为是正确的。 Subclass的实例有两个不同的ivars,即使它们具有相同的名称。 -[Subclass initSharedObject]初始化Subclass中声明的ivar。然后-[Superclass useSharedObject]使用Superclass中声明的ivar。那个ivar是nil所以这个电话悄然无所事事。