在观看iOS技术讲座并阅读类集群后,我决定将旧版iOS 6代码提取到私有子类:
@interface MyUIView : UIView @end // public
@interface MyUIViewiOS6 : MyUIView @end // private
@interface MyUIViewiOS7 : MyUIView @end // private
@implementation MyUIView
+ (id)alloc
{
// Don't loop on [super alloc]
if ([[self class] isSubclassOfClass:[MyUIView class]] &&
([self class] != [MyUIViewiOS6 class]) &&
([self class] != [MyUIViewiOS7 class]))
{
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
return [MyUIViewiOS6 alloc];
} else {
return [MyUIViewiOS7 alloc];
}
}
return [super alloc];
}
// Common implementation
@end
@implementation MyUIViewiOS6
// Legacy code
@end
@implementation MyUIViewiOS7
// iOS specific code
@end
这个实现很有效,直到我想要子类MyUIView。例如,如果我创建一个子类:
@interface MyRedUIView : MyUIView @end
然后按原样启动它:
[[MyRedUIView alloc] init]
将分配MyUIViewiOS6或MyUIViewiOS7类型的对象。有没有办法可以调整这种模式来支持子类化,以便MyRedUIView的超类动态切换到MyUIViewiOS6或MyUIViewiOS7?
答案 0 :(得分:2)
你已经达到了经典的双继承问题。您希望成为RedUIView
或GreenUIView
,并且可以是MyUIViewiOS6
或MyUIViewiOS7
视图。
由于objective-c不支持双重继承,因此您必须决定自己的行为和行为方式之间的区别。任何决定你是什么的东西,你都会上课。任何决定你行为的东西都会进入@protocol
然后才能实现。
我会继承MyUIView
,因为MyUIViewiOS6
和MyUIViewiOS7
对应于您的身份,然后针对某些功能实施Red
或Green
协议:< / p>
@interface MyRedUIView : MyUIView<RedProtocol> @end
您可以检查此类是否符合特定协议:
if ([class conformsToProtocol:@protocol(RedProtocol)]) {
self.color = [UIColor redColor];
}
如果他们 真的 都是你,那么你必须使用四个不同的类。
以下是使用类别的示例。假设您在问题中指定了MyUIView:
<强> GreenView.h 强>
#import "MyUIView.h"
#import "Green.h"
@interface MyUIView (GreenUIView) <Green>
-(BOOL) isGreen;
@end
@interface GreenView : MyUIView @end
<强> GreenView.m 强>
#import "GreenView.h"
@implementation MyUIView (GreenUIView)
-(BOOL) isGreen{
return [self conformsToProtocol:@protocol(Green)];
}
@end
@implementation GreenView @end
<强> Green.h 强>
@protocol Green <NSObject> @end
<强> AppDelegate.m 强>
#import "GreenView.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
GreenView* view = [[GreenView alloc] init];
NSLog(@"%@", [view isGreen]?@"yes":@"no");
return YES;
}
@end