子类化时的前向声明与#import
Forward Declaration vs #import when subclassing
我有 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
中转发声明 MyClassB
并在 MyClassC.m
中转发声明 #import "MyClassB.h"
或
b) #import MyClassB.h
在 MyClassA.h
一般来说,您应该尽可能在头文件中使用 @class
进行前向声明。唯一一次你可能不想这样做的是当你从一个超级 class 继承或声明协议一致性时,因为编译器需要知道那个 class 或协议中发生了什么.
对于这种情况,我会在头文件中对所有 属性 声明使用 @class,在 MyClassC.m 文件中使用 #import MyClassB.h
。这将允许 MyClassC 了解 MyClassB 上的所有属性。
从稍微不同的角度来看这个……你需要决定是否想让世界真正了解 myClassB
是 MyClassA
的 属性。例如,如果您可能只想宣传可以通过 MyClassA
获得的 myString
。这将其他 class 与了解 myString
的底层实现隔离开来。除非你需要暴露 MyClassB
你应该从 "rest of the world".
中隐藏它
在这种情况下,您可以按如下方式更改 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
以不同的方式导出。来自不同的 class 或完全不同的方法。免疫需要消耗myString
的代码
如果您需要公开 MyClassB
,那么您可以使用上面 Tyler 推荐的 @class
或 MyClassA.h 中的 #import MyClassB.h
。最佳实践规定前向声明 @class
。但有时不必记住在实现文件中导入大量文件的便利性会胜出。这是您的代码库,因此您可以选择最适合您的代码库。我一般是两者结合使用。
我有 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
中转发声明 MyClassB
并在 MyClassC.m
#import "MyClassB.h"
或
b) #import MyClassB.h
在 MyClassA.h
一般来说,您应该尽可能在头文件中使用 @class
进行前向声明。唯一一次你可能不想这样做的是当你从一个超级 class 继承或声明协议一致性时,因为编译器需要知道那个 class 或协议中发生了什么.
对于这种情况,我会在头文件中对所有 属性 声明使用 @class,在 MyClassC.m 文件中使用 #import MyClassB.h
。这将允许 MyClassC 了解 MyClassB 上的所有属性。
从稍微不同的角度来看这个……你需要决定是否想让世界真正了解 myClassB
是 MyClassA
的 属性。例如,如果您可能只想宣传可以通过 MyClassA
获得的 myString
。这将其他 class 与了解 myString
的底层实现隔离开来。除非你需要暴露 MyClassB
你应该从 "rest of the world".
在这种情况下,您可以按如下方式更改 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
以不同的方式导出。来自不同的 class 或完全不同的方法。免疫需要消耗myString
的代码
如果您需要公开 MyClassB
,那么您可以使用上面 Tyler 推荐的 @class
或 MyClassA.h 中的 #import MyClassB.h
。最佳实践规定前向声明 @class
。但有时不必记住在实现文件中导入大量文件的便利性会胜出。这是您的代码库,因此您可以选择最适合您的代码库。我一般是两者结合使用。