仅适用于类及其子类的属性

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

【讨论】:

以上是关于仅适用于类及其子类的属性的主要内容,如果未能解决你的问题,请参考以下文章

类及对象

Java异常 Exception类及其子类

php facetwp索引类及其子类

Format类及其子类功能和使用方法具体解释

访问修饰符与可选修饰符static的使用

面向对象编程