22

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

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

4

4 回答 4

15

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

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

于 2010-11-24T07:16:56.740 回答
10

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

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

@interface MyClass ()

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

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

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

例子:

基类.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

基类.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

子类.h

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

#import "BaseClass.h"

@interface ChildClass : BaseClass

-(void)test;

@end

子类.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

当您调用时#import,它基本上会将 .h 文件复制粘贴到您要导入它的位置。如果您有,则只有在设置了该名称的情况#ifdef下,它才会包含其中的代码。#define

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

于 2014-02-06T15:51:51.217 回答
0

您可以在子类实现中使用这样的语法。

@interface SuperClass (Internal)

@property (retain, nonatomic) NSString *protectedString;

@end
于 2013-01-12T11:34:49.133 回答
0

您可以使用类别来实现您的目的

@interface SuperClass (Protected)

@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIView *topMenuView;
@property (nonatomic, strong) UIView *bottomMenuView;

@end

在子类中,您将这个类别导入文件.m

于 2019-07-20T10:59:06.823 回答