【问题标题】:Is it ok to redeclare private ivars in a subclass to make them accessible?可以在子类中重新声明私有 ivars 以使其可访问吗?
【发布时间】:2013-06-15 18:37:08
【问题描述】:

当对列出 .h 文件中的私有 ivars 的 Apple 类进行子类化时,是否可以在子类 .m 文件内的类扩展 @interface 中重新声明您自己的子类中的这些 ivars,以使您的子类可以访问它们实施?

【问题讨论】:

    标签: objective-c cocoa-touch cocoa subclass foundation


    【解决方案1】:

    我在这里找到了完全符合我自己的答案:http://lists.apple.com/archives/cocoa-dev/2007/Feb/msg00939.html

    如果他们将其设为@private 而不是@protected,您将不得不假设 这是有原因的。这个原因当然可能只是 在您知道充分的理由之前,将所有内容都设为@private 是谨慎的 不要...

    也就是说,它可能非常明确地可以访问它 直接,即使技术上可行。

    安全的做法是在你自己的课堂上重新做所有事情,同时 请求超类的维护者揭露 公共/受保护界面中所需的功能。

    【讨论】:

    • 是的。它有点老了,不是很正式,但想法不错。
    【解决方案2】:

    您必须记住,在子类中声明实例变量不会重新声明具有相同名称的现有超类实例变量,无论声称的重新声明是在公共接口中还是在类扩展中.即使您使用相同的名称,它是不同的实例变量

    您可以自己尝试一下。例如:

    @interface Base : NSObject {
    @private
        int _number;
    }
    @end
    
    @implementation Base
    - (id)init { self = [super init]; if (self) _number = 10; return self; }
    - (void)logNumber { printf("base = %d\n", _number); }
    @end
    
    @interface Derived : Base
    @end
    
    @interface Derived () {
        int _number;
    }
    @end
    
    @implementation Derived
    - (id)init { self = [super init]; if (self) _number = 20; return self; }
    - (void)logNumberDerived { printf("derived = %d\n", _number); }
    @end
    
    int main(void) {
        Derived *o = [Derived new];
        [o logNumber];
        [o logNumberDerived];
        return 0;
    }
    

    输出:

    base = 10
    derived = 20
    

    因为超类中的_number 与子类(扩展)中的_number 不同。如果您使用nm -a 检查二进制输出中的符号,您会注意到编译器生成了两个不同的符号:

    s _OBJC_IVAR_$_Base._number
    s _OBJC_IVAR_$_Derived._number
    

    【讨论】:

    • 有趣。但是大概,如果它们以其他方式声明相同,则您的示例表明在 super 中实现的方法中引用的方法将是在 super 中声明的方法。在子类中声明的方法中引用的那个将是在子类中声明的那个?
    • @uchuugaka 正确。由于超类 ivar 是私有的,因此子类无法访问该 ivar,它只能看到自己的不同 ivar。您需要付出额外的努力(例如,使用 Objective-C 运行时 API)才能访问超类 ivar。
    • 已验证。我用几种变体、setter、getter 和属性对此进行了测试,并且确实如你所说。当 ivar 是一个对象,其类是 ivar 的父类时,这种行为很容易“似乎”起作用,我“认为”我正在重新声明......(是的,我就是这样得出这个问题的,但是使用unsubclassable C 类型 ivar 更清楚!)
    • 分类也做不到。我学到了一些东西。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2017-04-11
    • 2017-12-20
    • 2017-05-12
    • 2016-11-28
    • 2014-05-30
    • 2010-10-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多