前向声明与#import的子类化
我有MyClassA
,它有一个MyClassB
类型的属性
//
// MyClassA.h
//
@interface MyClassA : NSObject
@property (strong, nonatomic, readonly) MyClassB *myClassB;
@end
MyClassB
有一个属性myString
。
//
// MyClassB.h
//
@interface MyClassB : NSObject
@property (copy, nonatomic, readonly) NSString *myString;
@end
我有MyClassC
需要在它的实现中访问myString
。
我是不是该 -
一)正向声明MyClassB
在MyClassA.h
和#import "MyClassB.h"
在MyClassC.m
要么
b)中#import MyClassB.h
在MyClassA.h
一般来说,您应该在头文件中尽可能使用@class
进行声明。 你可能不希望这样做的唯一时候是从超类继承或声明协议一致性,因为编译器需要知道该类或协议中发生了什么。
对于这个实例,我将使用@class来处理头文件中的所有属性声明,以及MyClassC.m文件中的#import MyClassB.h
。 这将允许MyClassC知道MyClassB上的所有属性。
从稍微不同的角度来看这个......你需要决定是否要世界真正了解myClassB
是的属性MyClassA
。 例如,如果您只想宣传可以通过MyClassA
获取的myString
。 这使得其他类不知道myString
的底层实现。 除非你需要公开MyClassB
否则你应该将它从“其他地方”中隐藏起来。
在这种情况下,您可以按如下方式更改MyClassA.h:
//
// MyClassA.h
//
@interface MyClassA : NSObject
@property (strong, nonatomic, readonly) NSString *myString;
@end
在MyClassA.m中,您可以执行以下操作。
//
// MyClassA.m
//
#import "MyClassA.h"
#import "MyClassB.h"
@interface MyClassA()
@property (strong, nonatomic) MyClassB *myClassB;;
@end
@implementation MyClassA
// Other meaningful code omitted
- (NSString *)myString {
return self.myClassB.myString;
}
@end
请注意,我在这里所做的是使用匿名类别为myClassB
内部定义属性。
这里的关键是不让MyClassB
暴露给其他人是否MyClassB
。 这种方法的主要优点是你的代码更具延展性。 让我们说myString
得到一个不同的方式。 完全不同的课程或不同的方法。 需要消费myString
的代码被免疫。
如果你需要公开MyClassB
,那么你可以按照Tyler的建议使用@class
,或者从@class
中使用#import MyClassB.h
。 最佳做法规定了前向声明@class
。 但有时,不必记住在实现文件中导入大量文件的便利性可以胜出。 这是你的代码库,所以你可以选择哪一个最适合你。 我通常使用这两者的组合。