Objective-C:你如何从子类访问父属性?

如果我定义了这个类,如何在没有编译器错误的情况下访问子类中的someObject属性?

 @interface MyBaseClass // someObject property not declared here because I want it to be scoped // protected. Only this class instance and subclass instances should be // able to see the someObject property. @end // This is a private interface extension...properties declared here // won't be visible to subclasses. However, I don't see any way to // declare protected properties... @interface MyBaseClass (private) @property (nonatomic, readwrite, retain) NSObject *someObject; @end 

 @interface MySubclass : MyBaseClass @end @implementation MySubclass - (id) init { // Try to do something with the super classes' someObject property. // Always throws compile errors. // Semantic Issue: Property 'someObject' not found // object of type 'MySubclass *' self.someObject = nil; } @end 

我显然不了解在objective-c中inheritance是如何工作的。 有人能教导我吗?

你之后的解决scheme是在一个类扩展中声明MyBaseClass私有属性:

 @interface MyBaseClass () @property (nonatomic, readwrite, retain) NSObject *someObject; @end 

然后您可以自由地在MyBaseClass MySubclass中进行声明。 这让MySubclass知道这些属性,以便它的代码可以谈论它们。

如果重复困扰你,将类扩展名放在它自己的.h文件中,并将其导入到两个.m文件中。

我将从我自己的代码给出一个例子。 这里是MyDownloaderPrivateProperties.h

 @interface MyDownloader () @property (nonatomic, strong, readwrite) NSURLConnection* connection; @property (nonatomic, copy, readwrite) NSURLRequest* request; @property (nonatomic, strong, readwrite) NSMutableData* mutableReceivedData; @end 

没有对应的.m文件,这就是这个文件的全部内容; 它是纯粹的说明性的。 下面是MyDownloader.m的开始:

 #import "MyDownloader.h" #import "MyDownloaderPrivateProperties.h" @implementation MyDownloader @synthesize connection=_connection; @synthesize request=_request; @synthesize mutableReceivedData=_mutableReceivedData; // ... 

下面是它的子类MyImageDownloader.m的开始:

 #import "MyImageDownloader.h" #import "MyDownloaderPrivateProperties.h" 

问题解决了。 隐私被保留下来,因为这些是唯一导入MyDownloaderPrivateProperties.h的类,所以它们是唯一知道这些属性的类,就编译器而言(这就是Objective-C中的隐私)。 子类可以访问由超类合成访问器的私有属性。 我相信这就是你想要完成的。

这就是你如何访问它们。 你怎么声明是什么咬你的:

 @interface MyBaseClass : NSObject @property (nonatomic, readwrite, retain) NSObject *someObject; @end 

这是声明一个新的objc类的正常方法。

通过添加括号(而不是声明超类NSObject在这种情况下),你已经声明了一个类扩展,这可能是不可见的子类(通过包含)。

你可能永远不需要在objc中声明一个根类:

 @interface MyBaseClass // << superclass omitted @property (nonatomic, readwrite, retain) NSObject *someObject; @end 

NSObject(或者假定你是苹果系统的一个子类)应该是基类,除非你非常有经验,知道什么是根类。

类扩展通常用来“模拟”私有接口。 通过模拟,编译器不强制执行此操作,因为它将在其他语言中执行。 例如,所有消息仍然是dynamic的,尽pipe如果用相同的select器声明,子类可能(不知不觉地)覆盖扩展中的方法。

用你的基类名称后面的()来判断,看起来你在你的类实现中声明了一个私有接口扩展,是这样吗? 如果是这样,variables只能从该类实现中访问。

你的MyBaseClass是否直接从NSObjectinheritance?

如果是这样,您需要在接口文件中声明someObject属性,如下所示:

 @interface MyBaseClass : NSObject { } @property (nonatomic, retain) NSObject *someObject; 

然后像你已经做的那样综合它。

这是符合大部分目标的替代scheme。

在你的头部,定义接口

 @interface MyBaseClass : NSObject { NSObject *inheritableObject; } @property (readonly) NSObject *inheritableObject; 

现在,您可以编辑MyBaseClass中的inheritableObject以及任何inheritance自MyBaseClass的Class。 但是,从外部看,它是只读的。 不像@interface MyBaseClass()那样是私有的,但受到不受控制的更改的保护。

super.someObject = nil; 。 inheritance意味着MyBaseClass是你的类。