我只是想学习目标-c。
我已经在不同语言中看到了AbstractFactory模式的维基百科示例。
这里是按钮定义:
@protocol Button
- (void)paint;
@end
@interface WinButton : NSObject <Button>
@end
这是一家工厂:
@implementation WinFactory
- (id)createButton {
return [[[WinButton alloc] init] autorelease];
}
@end
就我而言,obj-c的id
关键字应该类似于C#&#39; var
或C ++ 11&{39} auto
,
正确?
所以我的问题是:
为什么让工厂返回未指定类型的通用对象? 这是一个错误(让工厂返回其他非Button的东西)还是有任何理由这样做?
我以这种方式写工厂:
@implementation WinFactory
- (id<Button>)createButton {
return [[[WinButton alloc] init] autorelease];
}
@end
我错了吗?
答案 0 :(得分:6)
为什么让工厂返回未指定类型的通用对象?
在许多情况下,您看到id
返回,这是因为它们不是一致的类型(真正的抽象对象),或者是因为会引入隐式的向上转换。
这是一个错误(让工厂返回其他非Button的东西)还是有任何理由这样做?
这不是错误。当然,你不应该返回一个不匹配的类型。
我会这样写一个工厂:......我错了吗?
@implementation WinFactory
- (id<Button>)createButton {
return [[[WinButton alloc] init] autorelease];
}
@end
这种情况下的最大问题是ObjC的输入类型非常松散,您应该努力确保所有选择器的参数和返回类型匹配。也就是说,所有翻译中的每个createButton
都应该返回相同的类型并且具有相同的参数类型。有时您必须选择更具描述性的名称,以避免编译器的歧义。
这应该解释为什么+[NSString string]
会返回id
- 如果它返回NSString
,那么+[NSMutableString string]
可能会成为警告的来源。这是因为编译器可能具有将方法声明与动态实例匹配的困难(不可能)时间。这也可以帮助您理解选择器的'罗嗦'命名,例如方便构造函数,它也包含方法中的类型(例如+[NSDictionary dictionaryWithObject:]
而不是简单的+[NSDictionary withObject:]
)。
但是要回答你的问题:id<Button>
或NSObject<Button>*
或其他一些合格的类型就好了 - 只要您可以使用该常用方法签名。您正在引入类型限定,这有助于编译器帮助您。
答案 1 :(得分:4)
这里更正确的返回类型是:
- (id<Button>)createButton;
这意味着返回的类型是符合<Button>
协议的对象。我可以修改WP页面,以便更清楚一些。 <Button>
协议还应继承<NSObject>
协议以保证完整性(并简化实际使用)。
请注意,ObjC中的抽象工厂模式有点不寻常。我试图想一下它在UIKit或Foundation中使用的情况。类在内部处理(例如在NSNumber
中)并且被称为类集群更常见。
要小心尝试在ObjC中使用C ++或C#样式进行编码。 ObjC不是静态语言,使用的模式通常是完全不同的。 (我不是说AF是一种静态模式。它可以在ObjC中使用得很好。我只是说你在尝试学习ObjC时看着它的事实意味着你可能会向后接近它,学习“我如何在ObjC中做这个C ++”,而不是学习“我如何在ObjC中开发。”)
答案 2 :(得分:0)
Objective-C具有类集群的概念,它是抽象工厂。 See this answer.