繁体   English   中英

objective-c中的类扩展

[英]class extension in objective-c

我正在通过阅读书本来学习object-c。 当我阅读关于类扩展的章节时,本书给出了以下示例代码:

// A class extension
@interface BNREmployee ()

@property (nonatomic) unsigned int officeAlarmCode;

@end

@implementation BNREmployee
...
@end

该书说,不是BNREmployee实例的BNREmployee不能再看到这个属性 officeAlarmCode 它举了一个例子:

BNREmployee *mikey = [[BNREmployee alloc] init];
unsigned int mikeysCode = mikey.officeAlarmCode;

此尝试将导致编译器错误,其中显示“No visible @interface声明实例方法officeAlarmCode”。

但是我很困惑。 我的意思是我觉得这本书的文字及其示例代码是矛盾的。 本书说,不是BNREmployee实例的BNREmployee不能再看到属性officeAlarmCode 但是,在上面的示例代码,是不是mikey的实例BNREmployee 为什么它看不到officeAlarmCode事件它是BNREmployee一个实例?

===更新=====

我正在读的本书就是本书。 第22章,第162页。

我只想验证这本书是以误导的方式解释的,我在这里寻找明确的解释。 因为书上说“那不是的实例对象BNREmployee ,像我这样的电子书阅读器不再能看到物业officeAlarmCode”,我觉得这暗示,是实例对象BNREmployee可以看到物业officeAlarmCode 这就是为什么我很困惑,因为mikey是一个实例BNREmployee但它不能访问officeAlarmCode。

Mikes是BNREmployee的一个实例。 但是该示例告诉您,属性officeAlarmCode没有公开,只能由BNREmployee对象在内部使用。

说“物体再也看不见”有点误导。 即使在比喻意义上,物体也看不到任何东西。 让我们说: 代码放置在类的实现之外无法看到属性。

根据Apple Docs1 。类扩展可以将自己的属性和实例变量添加到类2。类扩展通常用于扩展具有其他私有方法或属性的公共接口,以供在类本身的实现中使用。

因此,如果您在类扩展中声明该属性,则该属性仅对实现文件可见。 喜欢

BNREmployee.m

@interface BNREmployee ()

@property (nonatomic) unsigned int officeAlarmCode;

@end

@implementation BNREmployee

- (void) someMethod {
    //officeAlarmCode will be available inside implementation block to use
     _officeAlarmCode = 10;
}
@end

如果要在其他类中使用officeAlarmCode,例如,OtherEmployee类,则需要在BNREmployee.h文件中创建具有readOnly或readWrite访问权限的officeAlarmCode属性。 那你可以像使用它一样

BNREmployee.h

@property (nonatomic, readOnly) unsigned int officeAlarmCode; //readOnly you can just read not write 

OtherEmployee.m

import "BNREmployee.h"
@interface OtherEmployee ()

@property (nonatomic) unsigned int otherAlarmCode;

@end

@implementation OtherEmployee

您可以创建的实例BNREmployee和可分配officeAlarmCodeotherAlarmCode财产像下面

BNREmployee *bnrEmployee = [BNREmployee alloc] init];
_otherAlarmCode = bnrEmployee.officeAlarmCode;
BNREmployee *mikey = [[BNREmployee alloc] init];
unsigned int mikeysCode = mikey.officeAlarmCode;
  • 此代码位于文件中。 该文件(和该类)不是BNREmployee.m。此代码位于非BNREmployee对象中。 让我们调用这个代码存在的对象foo
  • mikey是一个BNREmployee对象。
  • 此代码尝试访问BNREmployee对象的officeAlarmCode属性。
  • 当foo想要使用BNREmployee对象(如mikey)时,它可以访问的属性只是BNREmployee.h中的属性。
  • 由于BNREmployee.h中不存在officeAlarmCode,因此foo无法访问mikey的officeAlarmCode属性,因为该属性不在界面中(BNREmployee.h文件)。
  • 由于mikey是BNREmployee对象,因此可以查看officeAlarmCode并使用它。
  • mikey的代码在哪里可以使用officeAlarmCode? mikey的代码在BNREmployee.m文件中。 因此,唯一可以使用officeAlarmCode的代码是BNREmployee的实现。

考虑上下文,只要扩展接口在给定上下文中“可见”,任何其他类都可以访问在扩展名或任何类别中声明的属性。

例如,以下实现文件包含两个接口的实现: BaseObjectBaseObjectController 在其他类( BaseObjectController )的实现中,您可以通过getter和setter安全地使用“hidden”属性,因为声明接口是“可见的”。 如果将BaseObjectController的实现BaseObjectController看不到扩展声明的另一个文件-该代码将无法编译。

#import "BaseObject.h"
#import "BaseObjectController.h"

//  BaseObject    
@interface BaseObject()
@property (strong) NSString * idString;
@end

@implementation BaseObject
@end

//  BaseObjectController    
@implementation BaseObjectController
- (void) initBaseObject {
    BaseObject * bo = [BaseObject new];
    bo.idString = @"01234";
}
@end

我从中得到的是,物业officeAlarmCode只是中可见BNREmployee.m文件,它不会从访问main.m

要通过价值mikeysCode你必须创建一个返回的方法officeAlarmCode

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM