【问题标题】:Objective-C: How do I access parent private properties from subclasses?Objective-C:如何从子类访问父私有属性?
【发布时间】:2014-01-14 14:46:44
【问题描述】:
//Super class .h file

@interface MySuperClass : NSObject

@end

//Super class .m file

@interface MySuperClass ()

@property (nonatomic, strong) UITextField *emailField; 

@end

@implementation MySuperClass

-(void)accessMyEmailField {

   NSLog(@"My super email: %@", self.emailField.text);

}

@end


// ********** my subclass *******

//Subclass .h file

@interface MySubClass : MySuperClass

@end

//SubClass .m file

@interface MySubClass ()

@end

@implementation MySubClass

-(void)myEmail {

   NSLog(@"My subclass email: %@", self.emailField.text);

}

-(void)setMyEmailFromSubclass{

   self.emailField.Text = @"email@gmail.com"

}

@end
  1. 如何访问-(void)myEmail method中的emailField。
  2. 如何在子类-(void)setMyEmailFromSubclass 中设置电子邮件; , 并在超类 accessMyEmailField 中访问它

【问题讨论】:

    标签: ios iphone objective-c ios6 ios7


    【解决方案1】:

    您可以将这些属性的访问器放在第二个头文件中,并在“需要知道”的基础上导入该文件。 例如

    mySuperClass+undocumentedProperties.h

    #import "mySuperClass.h"
    
    @interface mySuperClass(undocumentedProperties)
    
      @property (nonatomic, strong) UITextField *emailField;
    
     @end
    

    mySuperClass.m

    #import "mySuperClass+undocumentedProperties.h"
    
    @interface mySuperClass()
    ///stuff that truly will be private to this class only
    // self.emailField is no longer declared here..
    @end
    
    @implementation mySuperClass
    
    @synthesize emailField; //(not really needed anymore)
    
    /// etc, all your code unaltered
    @end
    

    mySubclass.h

    #import "mySuperClass.h"
    @interface mySubclass:mySuperClass
    
    ///some stuff
    @end
    

    mySubclass.m

    #import "mySubclass.h"
    #import "mySuperClass+undocumentedProperties.h"
    @implementation
    
    //off you go, this class is now 'aware' of this secret inherited property..
    
    @end
    

    显然 MySuperClass.m 将不得不导入这个 .h 文件以及它的默认文件(或者实际上,默认文件是内置到这个文件中的),但是您的子类也可以导入它(直接导入到它们的 .h 文件中)。 m 文件,因此这些属性对类保持私有。这不是一个适当的类别,因为没有相应的 mySuperClass+undocumentedProperties.m 文件(如果您尝试过,您无法为这些秘密属性合成支持 iVar。享受 :)

    【讨论】:

    • 对我来说有点不清楚。你能在我提供的例子中展示你会怎么做吗?
    • 如果我只有一个类需要访问,我倾向于将这些信息放在另一个类中,以减少文件数量。但如果不止一个需要半私人访问,这确实是最好的解决方案。
    • @KendallHelmstetterGelner 谢谢。今天学到了一些新东西。
    • 还有 Pasha,这可能会或可能不会很明显,但在这个“秘密标题”中可能很容易出现未记录的方法/函数原型,以便子类查看,例如-(无效)做某事;等
    • 嗯,这是一个类似于我使用的概念,有时一开始并不清楚,特别是如果来自其他 oop 语言,需要重新声明什么以及如何访问超类道具和成员。就像 Zaph 解释的那样,“私有”成员应该始终保持“私有”,并且永远不会在其基类范围之外可见。如果我们从其子类访问“超级”成员——应该对外部世界保持隐藏——我们需要在其他 oop 语言中称为“受保护”成员可见性的东西。我仍然没有找到在 Objective-C 中复制的干净而好的方法
    【解决方案2】:

    从您的超类中复制您想要的方法的私有接口部分 - 或者换句话说,复制到您的 Subclass.m 文件中:

    @interface MySuperClass ()
    @property (nonatomic, strong) UITextField *emailField; 
    @end
    

    (将其放在现有的@interface MySubClass () 代码上方)

    现在您的子类知道该方法存在于超类中并且可以使用它,但您不会将其暴露给其他任何人。

    【讨论】:

    • 但这是一个可怕的概念!它们可以被删除或大幅更改。超类不应该依赖于子类,但这正是导致的原因,超类无法在不更改使用它们的子类的情况下更改其内部实现。
    • In .m subclass ('@interface MySubClass () @property (nonatomic, strong) UITextField *emailField; @end') 这样我可以设置超类属性,但是在超类中我的 emailField 仍然为空
    • Zaph:我只是说如何,而不是如果你应该。 @Pasha:您可能正在尝试在 IB 或 viewDidLoad 或类似的东西设置 emailField 之前设置它。
    • @Zaph 谢谢老兄。这正是我一直在寻找的。解决了。​​
    【解决方案3】:

    私有属性的全部意义正是如此,您不应该想要访问它们。因为它们是私有的,所以它们可以更改或删除,从而破坏依赖它们的子类。

    话虽如此,它们并不是真正私人的,只是没有“发布”。可以调用,因为 Objective-C 是一种运行时动态语言。

    【讨论】:

    • 这正是我想要做的。我不想发布 emailField,这就是为什么我将它保存在 .m 文件中,但我需要从子类 .m 文件中访问它
    • 如果它们都是你的类,则创建两个头文件。一个带有公共声明,另一个带有私有声明。在超类和任何需要它的子类中导入私有和公共,但不要使私有标头可供其他人使用。这就是 Apple 处理它的公共和私有方法的做法。
    猜你喜欢
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    相关资源
    最近更新 更多