简体   繁体   English

objective-c中的类扩展

[英]class extension in objective-c

I am learning object-c by reading a book. 我正在通过阅读书本来学习object-c。 When I read the chapter about class extension, the book gives the following example code: 当我阅读关于类扩展的章节时,本书给出了以下示例代码:

// A class extension
@interface BNREmployee ()

@property (nonatomic) unsigned int officeAlarmCode;

@end

@implementation BNREmployee
...
@end

The book says objects that are not instances of BNREmployee can no longer see this property officeAlarmCode . 该书说,不是BNREmployee实例的BNREmployee不能再看到这个属性 officeAlarmCode It makes an example: 它举了一个例子:

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

This attempt would result in a compiler error that reads “No visible @interface declares the instance method officeAlarmCode”. 此尝试将导致编译器错误,其中显示“No visible @interface声明实例方法officeAlarmCode”。

But I get confused. 但是我很困惑。 I mean I feel the book's words & its example code are contradictory. 我的意思是我觉得这本书的文字及其示例代码是矛盾的。 Book says objects that are not instance of BNREmployee can not longer see property officeAlarmCode . 本书说,不是BNREmployee实例的BNREmployee不能再看到属性officeAlarmCode But in the example code above, isn't mikey an instance of BNREmployee ? 但是,在上面的示例代码,是不是mikey的实例BNREmployee Why it cannot see officeAlarmCode event it is an instance of BNREmployee ? 为什么它看不到officeAlarmCode事件它是BNREmployee一个实例?

=== UPDATE ===== ===更新=====

The book I am reading is this one . 我正在读的本书就是本书。 Chapter 22, page 162. 第22章,第162页。

I just want to verify that the book explained in a misleading way & I am looking for a clear explanation here. 我只想验证这本书是以误导的方式解释的,我在这里寻找明确的解释。 Because book says "objects that are NOT instance of BNREmployee can no longer see property officeAlarmCode", for the book reader like me, I feel it hints objects that are instance of BNREmployee CAN SEE property officeAlarmCode . 因为书上说“那不是的实例对象BNREmployee ,像我这样的电子书阅读器不再能看到物业officeAlarmCode”,我觉得这暗示,是实例对象BNREmployee可以看到物业officeAlarmCode That's why I am confusing, because mikey is an instance of BNREmployee but it can't access officeAlarmCode. 这就是为什么我很困惑,因为mikey是一个实例BNREmployee但它不能访问officeAlarmCode。

Mikes is an instance of BNREmployee. Mikes是BNREmployee的一个实例。 But the example is telling you that the property officeAlarmCode is not exposed and can only be used by BNREmployee objects internally. 但是该示例告诉您,属性officeAlarmCode没有公开,只能由BNREmployee对象在内部使用。

It is a little bit misleading to say "objects can no longer see". 说“物体再也看不见”有点误导。 Objects doesn't see anything, even in the figurative sense. 即使在比喻意义上,物体也看不到任何东西。 Let`s say: Code placed outside the implementation of the class cannot see the property. 让我们说: 代码放置在类的实现之外无法看到属性。

As per the Apple Docs 1. a class extension can add its own properties and instance variables to a class 2. Class extensions are often used to extend the public interface with additional private methods or properties for use within the implementation of the class itself. 根据Apple Docs1 。类扩展可以将自己的属性和实例变量添加到类2。类扩展通常用于扩展具有其他私有方法或属性的公共接口,以供在类本身的实现中使用。

so if you declare the property in class extension it will be visible only to the implementation file. 因此,如果您在类扩展中声明该属性,则该属性仅对实现文件可见。 like 喜欢

in BNREmployee.m 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

If you want to use officeAlarmCode in other classes, let's say OtherEmployee class then you need to create officeAlarmCode property in BNREmployee.h file with readOnly or readWrite access. 如果要在其他类中使用officeAlarmCode,例如,OtherEmployee类,则需要在BNREmployee.h文件中创建具有readOnly或readWrite访问权限的officeAlarmCode属性。 Then you can use it like 那你可以像使用它一样

BNREmployee.h

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

in OtherEmployee.m OtherEmployee.m

import "BNREmployee.h"
@interface OtherEmployee ()

@property (nonatomic) unsigned int otherAlarmCode;

@end

@implementation OtherEmployee

you can create instance of BNREmployee and can assign officeAlarmCode value to otherAlarmCode property like below 您可以创建的实例BNREmployee和可分配officeAlarmCodeotherAlarmCode财产像下面

BNREmployee *bnrEmployee = [BNREmployee alloc] init];
_otherAlarmCode = bnrEmployee.officeAlarmCode;
BNREmployee *mikey = [[BNREmployee alloc] init];
unsigned int mikeysCode = mikey.officeAlarmCode;
  • This code is in a file. 此代码位于文件中。 That file (and that class) isn't BNREmployee.m .This code is in a non-BNREmployee object. 该文件(和该类)不是BNREmployee.m。此代码位于非BNREmployee对象中。 Lets call the object in which this code exists foo . 让我们调用这个代码存在的对象foo
  • mikey is a BNREmployee object. mikey是一个BNREmployee对象。
  • This code tries to access the officeAlarmCode property of a BNREmployee object. 此代码尝试访问BNREmployee对象的officeAlarmCode属性。
  • When foo wants to use a BNREmployee object (like mikey), the properties it can access are only the ones in BNREmployee.h. 当foo想要使用BNREmployee对象(如mikey)时,它可以访问的属性只是BNREmployee.h中的属性。
  • As officeAlarmCode doesn't exist in BNREmployee.h, foo cannot access the officeAlarmCode property of mikey, because this property isn't in the interface ( BNREmployee.h file). 由于BNREmployee.h中不存在officeAlarmCode,因此foo无法访问mikey的officeAlarmCode属性,因为该属性不在界面中(BNREmployee.h文件)。
  • As mikey is a BNREmployee object, it can see the officeAlarmCode, and use it. 由于mikey是BNREmployee对象,因此可以查看officeAlarmCode并使用它。
  • Where is mikey's code which can use the officeAlarmCode? mikey的代码在哪里可以使用officeAlarmCode? mikey's code is in BNREmployee.m file. mikey的代码在BNREmployee.m文件中。 So the only code that can use the officeAlarmCode is the implementation of BNREmployee. 因此,唯一可以使用officeAlarmCode的代码是BNREmployee的实现。

Think contexts, any other class can access the properties declared at the extensions or any categories as far as the extended interfaces are "visible" at the given context. 考虑上下文,只要扩展接口在给定上下文中“可见”,任何其他类都可以访问在扩展名或任何类别中声明的属性。

For example, the following implementation file contains implementation of two interfaces: BaseObject and BaseObjectController . 例如,以下实现文件包含两个接口的实现: BaseObjectBaseObjectController At the implementation of the other class ( BaseObjectController ) you can safely use the "hidden" property via getters and setters because the declaration interface is "visible". 在其他类( BaseObjectController )的实现中,您可以通过getter和setter安全地使用“hidden”属性,因为声明接口是“可见的”。 If you move the implementation of BaseObjectController to another file that can't see declaration of the extension - this code won't compile. 如果将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

What I got from it is that the property officeAlarmCode is only visible within the BNREmployee.m file, it will not be accessible from main.m . 我从中得到的是,物业officeAlarmCode只是中可见BNREmployee.m文件,它不会从访问main.m

To pass the value to mikeysCode you would have to create a method that returns officeAlarmCode . 要通过价值mikeysCode你必须创建一个返回的方法officeAlarmCode

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

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