仅适用于类及其子类的属性
Posted
技术标签:
【中文标题】仅适用于类及其子类的属性【英文标题】:Properties for Class and Its Subclasses Only 【发布时间】:2011-05-14 22:29:09 【问题描述】:是否可以定义仅对定义它们的类和该类的子类可用的属性?
换一种说法,有没有办法定义受保护的属性?
【问题讨论】:
【参考方案1】:从技术上讲,没有。属性实际上只是方法,所有方法都是公共的。我们在 Objective-C 中“保护”方法的方式是不让其他人知道它们。
实际上,是的。您可以在类扩展中定义属性,并在主实现块中仍然@synthesize
它们。
【讨论】:
要被“保护”,类扩展接口需要在一个单独的头文件中被包含在类及其子类中。 据我所知,在基类接口扩展中声明的任何属性都不适用于子类——它们是私有的,不受保护的。请参阅此 SO 讨论:***.com/questions/5588799/… @Harkonian 如果您自己声明选择器,您可以随时调用它。除了简单地隐藏它的声明之外,没有像“保护”一个方法这样的东西。 Objective-C 没有受保护或私有方法的概念。仅限受保护的或私有的 ivars。【参考方案2】:这可以通过使用包含在基类和子类的实现文件中的类扩展(而不是类别)来实现。
类扩展的定义类似于类别,但没有类别名称:
@interface MyClass ()
在类扩展中,您可以声明属性,这些属性将能够合成支持的 ivars(XCode > 4.4 自动合成 ivars 也适用于此)。
在扩展类中,您可以覆盖/优化属性(将只读更改为读写等),并添加对实现文件“可见”的属性和方法(但请注意,属性和方法并不是真正的私有的,仍然可以被选择器调用)。
其他人建议为此使用单独的头文件 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
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
ChildClass.h
// this will import BaseClass.h without the class extension
#import "BaseClass.h"
@interface ChildClass : BaseClass
-(void)test;
@end
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
当您调用#import
时,它基本上会将 .h 文件复制粘贴到您要导入它的位置。
如果您有#ifdef
,则只有在设置了具有该名称的#define
时,它才会包含其中的代码。
在您的 .h 文件中,您没有设置定义,因此任何导入此 .h 的类都不会看到受保护的类扩展。
在基类和子类 .m 文件中,在使用 #import
之前使用 #define
,以便编译器包含受保护的类扩展。
【讨论】:
【参考方案3】:你可以在子类实现中使用这样的语法。
@interface SuperClass (Internal)
@property (retain, nonatomic) NSString *protectedString;
@end
【讨论】:
【参考方案4】:你可以使用一个类别来达到你的目的
@interface SuperClass (Protected)
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIView *topMenuView;
@property (nonatomic, strong) UIView *bottomMenuView;
@end
在子类中,您将这个类别导入文件 .m
【讨论】:
以上是关于仅适用于类及其子类的属性的主要内容,如果未能解决你的问题,请参考以下文章