继承子类时的前向声明vs #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在它的实现。

我应该-

a)前向声明MyClassA.h中的MyClassBMyClassC.m中的#import "MyClassB.h"

b) #import MyClassB.h in MyClassA.h

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

对于这个例子,我将使用@class在你的头文件中的所有属性声明,并在你的MyClassC中的#import MyClassB.h。m文件。这将允许MyClassC知道MyClassB的所有属性

从稍微不同的角度来看…你需要决定你是否想让世界真正知道myClassBMyClassA的属性。例如,如果您可能只想宣传可以通过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暴露给其他人是否有意义。这种方法的主要优点是您的代码更具延展性。假设myString以另一种方式衍生。从不同的类或不同的方法。需要消耗myString的代码免疫。

如果你需要暴露MyClassB,那么你可以使用上面Tyler推荐的@class或MyClassA.h中的#import MyClassB.h。最佳实践规定正向声明@class。但有时,不需要记住在实现文件中导入大量文件的便利性会胜出。这是您的代码库,因此您可以选择最适合您的代码库。我通常使用两者的组合

最新更新