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

22

是否有可能定义在类及其子类中可用的属性,也就是说,是否有一种方法定义受保护的属性?

4个回答

15

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

实际上,可以通过在类扩展中定义属性,然后在主要的实现块中使用 @synthesize 来实现私有属性。


1
为了实现“保护”,类扩展接口需要放在单独的头文件中,以便包含在类及其子类中。 - JeremyP
据我所知,基类接口扩展中声明的任何属性都不可用于子类 - 它们是私有作用域,而不是受保护的。请参阅此SO讨论:https://dev59.com/km035IYBdhLWcg3wKsqa - memmons
@Harkonian,如果您自己声明选择器,则始终可以调用它。除了隐藏其声明之外,没有“保护”方法的概念。Objective-C没有受保护或私有方法的概念,只有受保护或私有成员变量。 - Dave DeLong

9
这可以通过使用类扩展(而不是类别)来实现,您需要在基类和子类的实现文件中都包含该类扩展。
类扩展的定义类似于类别,但没有类别名称:
@interface MyClass ()

在类扩展中,可以声明属性,这些属性将能够合成后备变量(XCode > 4.4自动合成ivar在这里也有效)。
在扩展类中,可以重写/修改属性(将只读属性更改为可读写等),并添加属性和方法,这些属性和方法将对实现文件“可见”(但请注意,这些属性和方法并不是真正的私有属性,仍然可以通过选择器调用)。
其他人建议使用一个单独的头文件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文件中,你使用#define在使用#import之前,以便编译器将包括受保护的类扩展。

0
您可以在子类实现中使用这样的语法。
@interface SuperClass (Internal)

@property (retain, nonatomic) NSString *protectedString;

@end

0

你可以使用分类来达到你的目的

@interface SuperClass (Protected)

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

@end

在子类中,你需要在.m文件中导入这个分类。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接