类的属性及其子类

Jay*_*ase 22 properties protected objective-c instance-variables

是否可以定义仅对它们所定义的类可用的属性,以及该类的子类?

换句话说,有没有办法定义受保护的属性?

Dav*_*ong 15

从技术上讲,没有.属性实际上只是方法,所有方法都是公共的.我们"保护"在Objective-C方法的方法是不让其他人知道他们.

实际上,是的.您可以在类扩展中定义属性,但仍然@synthesize可以在主实现块中定义它们.


d4n*_*4n3 10

这可以通过使用包含在基类和子类的实现文件中的类扩展(非类别)来实现.

类扩展的定义类似于类别,但没有类别名称:

@interface MyClass ()
Run Code Online (Sandbox Code Playgroud)

在类扩展中,您可以声明属性,这将能够合成支持ivars(XCode> 4.4自动合成的ivars也适用于此处).

在扩展类中,您可以覆盖/优化属性(将readonly更改为readwrite等),并添加对实现文件"可见"的属性和方法(但请注意,属性和方法不是真正的私有,并且可以仍然被选择器调用).

其他人建议使用单独的头文件MyClass_protected.h,但这也可以在主头文件中使用#ifdef如下:

例:

BaseClass.h

@interface BaseClass : NSObject

// foo is readonly for consumers of the class
@property (nonatomic, readonly) NSString *foo;

@end


#ifdef BaseClass_protected

// this is the class extension, where you define 
// the "protected" properties and methods of the class

@interface BaseClass ()

// foo is now readwrite
@property (nonatomic, readwrite) NSString *foo;

// bar is visible to implementation of subclasses
@property (nonatomic, readwrite) int bar;

-(void)baz;

@end

#endif
Run Code Online (Sandbox Code Playgroud)

BaseClass.m

// this will import BaseClass.h
// with BaseClass_protected defined,
// so it will also get the protected class extension

#define BaseClass_protected
#import "BaseClass.h"

@implementation BaseClass

-(void)baz {
    self.foo = @"test";
    self.bar = 123;
}

@end
Run Code Online (Sandbox Code Playgroud)

ChildClass.h

// this will import BaseClass.h without the class extension

#import "BaseClass.h"

@interface ChildClass : BaseClass

-(void)test;

@end
Run Code Online (Sandbox Code Playgroud)

ChildClass.m

// this will implicitly import BaseClass.h from ChildClass.h,
// with BaseClass_protected defined,
// so it will also get the protected class extension

#define BaseClass_protected 
#import "ChildClass.h"

@implementation ChildClass

-(void)test {
    self.foo = @"test";
    self.bar = 123;

    [self baz];
}

@end
Run Code Online (Sandbox Code Playgroud)

当您调用时#import,它基本上将.h文件复制粘贴到您导入它的位置.如果你有#ifdef,那么如果设置#define了那个名字,它将只包含里面的代码.

在.h文件中,您没有设置define,因此导入此.h的任何类都不会看到受保护的类扩展.在基类和子类.m文件中,您在使用#define之前使用,#import以便编译器将包含受保护的类扩展.