假设我有一个类BasicDate
,并且BasicDate
的子类名为EuroDate
。类别之间的差异是月 - 日 - 年与日 - 月 - 年。我知道让同一个类的方法以不同的方式输出它们可能会更好......但这不是这个问题的重点。
BasicDate
包含以下init method
:
-(id)initWithMonth:(int)m andDay:(int)d andYear:(int)y {
if(self = [super init]) { /*initialize*/ } return self;
}
然后匹配的factory method
看起来像这样:
+(BasicDate)dateWithMonth:(int)m andDay:(int)d andYear:(int)y {
return [[BasicDate alloc] initWithMonth: m andDay: d andYear: y];
}
但是如果我的子类EuroDate
更像这样使用factory method
:
+(EuroDate)dateWithDay:(int)d andMonth:(int)m andYear:(int)y {
return [[EuroDate alloc] initWithDay: d andMonth: m andYear: y];
} //we can assume that EuroDate includes this init method...
这一切都很好。现在,我们假设这两个类都有自己的description method
,它会为MMDDYYYY
打印BasicDate
,但DDMMYYYY
打EuroDate
。这仍然很好。
但如果我这样做:
EuroDate today = [EuroDate dateWithMonth:10 andDay:18 andYear:2013];
这将调用BasicDate
已继承的EuroDate
工厂方法。问题是,还记得BasicDate
的工厂方法看起来如何吗? return [[BasicDate alloc] ...]
today
多变形为BasicDate
,尽管我想将其存储为EuroDate
,因此如果我调用description
方法,则会打印10182013
而不是18102013
。
我发现这个问题有两种解决方案。
解决方案1:更改BasicDate
的工厂方法。而不是return [[BasicDate alloc] ...
,我可以改为return [[[self class] alloc] ...]
这样做可以让我将此方法用于BasicDate
或任何BasicDate
的子类,它将返回右侧对象类型。
解决方案2:Override
工厂方法。我是否覆盖它以抛出异常或覆盖它以执行return [[EuroDate alloc] ...]
。覆盖它的问题是我必须覆盖每个子类的每个工厂方法。
哪个更好?我可能缺少两种可能的解决方案有哪些缺点?什么被认为是在Objective C中处理这个问题的标准方法?
答案 0 :(得分:3)
您通常应在工厂方法中使用[[[self class] alloc] init...]
以确保它们创建正确类的实例。请注意,class
不是属性(事实上,没有'类属性'这样的东西),因此使用点语法是不合适的。
修改强>
正如@ArkadiuszHolko(和Rob,谢谢)指出的那样,您现在应该使用instancetype
而不是id
作为返回值,以获得强类型的好处,同时保持类型灵活性子类。顺便说一句,Apple的命名惯例建议避免在方法名称中使用“和”这个词。因此,请考虑重写您的便利方法:
+ (instancetype)dateWithMonth:(int)month day:(int)day year:(int)year
{
return [[self alloc] initWithMonth:month day:day year:year];
}