子类化时转发声明vs #import

时间:2016-09-01 20:17:24

标签: objective-c import include forward-declaration

我有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

我应该 -

a)在MyClassBMyClassA.h#import "MyClassB.h"转发声明MyClassC.m

b)#import MyClassB.h

中的MyClassA.h

2 个答案:

答案 0 :(得分:2)

通常,您应该在头文件中尽可能使用@class转发声明。您可能不希望这样做的唯一时间是您从超类继承或声明协议一致性,因为编译器需要知道该类或协议中发生了什么。

对于这个实例,我会在头文件中使用@class进行所有属性声明,在MyClassC.m文件中使用#import MyClassB.h。这将允许MyClassC了解MyClassB上的所有属性。

答案 1 :(得分:2)

从一个稍微不同的角度看待这个......你需要决定是否希望世界真正了解myClassBMyClassA的属性。例如,如果您可能只想宣传可以通过myString获得的MyClassA。这使其他类无法了解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暴露给他人是否有意义。这种方法的主要优点是您的代码更具有可塑性。让我们说myString以不同的方式得出。从一个不同的类或不同的方法。需要消耗myString的代码被免疫。

如果您需要公开MyClassB,那么您可以使用上面Tyler建议的@class或MyClassA.h中的#import MyClassB.h。最佳做法规定向前宣布@class。但有时,不必记住在实现文件中导入大量文件的便利性可以胜出。这是你的代码库,所以你可以选择哪一个最适合你。我通常使用两者的组合。