4

我只是想学习目标-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#'svar或 C++11's auto,对吧?

所以我的问题是:

为什么让工厂返回一个未指定类型的通用对象?这是一个错误(让工厂返回其他不是按钮的东西)还是有任何理由这样做?

我会这样写一个工厂:

@implementation WinFactory
- (id<Button>)createButton {
    return [[[WinButton alloc] init] autorelease];
}
@end 

我错了吗?

4

3 回答 3

6

为什么让工厂返回一个未指定类型的通用对象?

在您看到返回的许多情况下id,这是因为它们的类型不一致(真正的抽象对象),或者是因为会引入隐式向上转换。

这是一个错误(让工厂返回其他不是按钮的东西)还是有任何理由这样做?

这不是错误。当然,您不应该返回不匹配的类型。

我会这样写工厂:……我错了吗?

@implementation WinFactory
- (id<Button>)createButton {
    return [[[WinButton alloc] init] autorelease];
}
@end

在这种情况下,最大的问题是 ObjC 的类型非常松散,您应该努力确保所有选择器的参数和返回类型都匹配。也就是说,createButton所有翻译中的每一个都应该返回相同的类型并具有相同的参数类型。有时您必须选择一个更具描述性的名称,以避免编译器产生歧义。

这应该解释为什么+[NSString string]返回id- 如果它返回NSString,那么+[NSMutableString string]可能是警告的来源。这是因为编译器可能很难(不可能)将方法声明与动态实例匹配。这也可以帮助您理解选择器的“冗长”命名,例如在方法中也包含类型的便利构造函数(例如+[NSDictionary dictionaryWithObject:],与 simple 相对+[NSDictionary withObject:])。

但是要解决您的问题:id<Button>或者NSObject<Button>*其他一些合格的类型就可以了-只要您可以使用该通用方法签名即可。您正在引入类型限定,它可以帮助编译器帮助

于 2012-08-27T13:28:34.400 回答
4

这里更正确的返回类型是:

- (id<Button>)createButton;

这意味着返回的类型是符合<Button>协议的对象。我可能会修复 WP 页面只是为了更清楚一点。该<Button>协议还应该从协议继承<NSObject>完整性(并简化实际使用)。

请注意,抽象工厂模式在 ObjC 中有些不寻常。我正在尝试考虑在 UIKit 或 Foundation 中使用它的情况。类在内部(例如 in NSNumber)处理这种情况更为常见,称为类集群。

尝试在 ObjC 中以 C++ 或 C# 风格编写代码时要非常小心。ObjC 不是一门静态语言,使用的模式往往大相径庭。(我并不是说 AF 是一种静态模式。它可以在 ObjC 中很好地使用。我只是说您在尝试学习 ObjC 时正在查看它的事实意味着您可能正在向后接近它,学习“我如何在 ObjC 中做这个 C++”而不是学习“我如何在 ObjC 中开发。”)

于 2012-08-27T13:29:06.723 回答
0

Objective-C 有类簇的概念,类簇是抽象工厂。 看到这个答案。

于 2014-08-16T05:47:54.197 回答