【问题标题】:Class Factory Methods implementation类工厂方法实现
【发布时间】:2012-12-30 16:08:50
【问题描述】:

因此,我正在阅读 Apple 的 Objective-C 文档(在进入 iphone 开发之前)。其中一个练习表明我应该创建一个指定的初始化程序(带有 3 个参数)和合适的工厂方法。

现在我根据自己的理解做了这个,但我无法实现工厂方法,因为我不知道是否应该在其实现中使用 alloc 和 init?

练习:

声明并实现一个新的指定初始化器,用于创建一个 XYZPerson 使用指定的名字、姓氏和出生日期, 以及合适的类工厂方法。不要忘记覆盖 init 调用指定的初始化器。

代码:

//.h 

-(id)initWithNameAndDob:(NSString *)fName last:(NSString *)lName birth:(NSDate *) dob;

//.m
-(id)initWithNameAndDob:(NSString *)fName last:(NSString *)lName birth:(NSDate *)dob{
    self = [super init];
    return [self initWithNameAndDob:fName last:lName birth:dob];
}

实施中缺少什么?

谢谢你,

【问题讨论】:

  • 工厂方法以+开头,实例方法以-开头。

标签: objective-c


【解决方案1】:

声明并实现一个新的指定初始化程序,用于使用指定的名字、姓氏和出生日期创建一个 XYZPerson...

您在声明中是正确的,但您的实现是递归的,因为它正在调用自己。做类似的事情

//.h
-(id)initWithNameAndDob:(NSString *)fName last:(NSString *)lName birth:(NSDate *) dob;
//.m
-(id)initWithNameAndDob:(NSString *)fName last:(NSString *)lName birth:(NSDate *)dob{
    if(self = [super init]) {
        // use the parameters to do something, eg.
        _fName = fName; // assuming you have an ivar called _fName 
        _lName = lName; // assuming you have an ivar called _lName
        _dob = dob; // assuming you have an ivar called _dob
    }
    return self;
}

然后

...以及合适的类工厂方法。

工厂方法是一种产生对象实例的类方法。最常见的实现是让它分配和初始化对象的一个​​新实例并返回它。

//.h
+(instancetype)personWithNameAndDob:(NSString *)fName last:(NSString *)lName birth:(NSDate *) dob {


//.m
+(instancetype)personWithNameAndDob:(NSString *)fName last:(NSString *)lName birth:(NSDate *) dob {
return [[XYZPerson alloc] initWithNameAndDob:fName last:lName birth:dob];
}

终于

别忘了重写 init 来调用指定的初始化器。

由于您设计的初始化程序是initWithNameAndDob:last:birth:,您的init 实现必须调用它。设计的初始化器的参数必须是合理的默认值,在这种情况下nil 很好。

-(id)init {
     return [self initWithNameAndDob:nil last:nil birth:nil];
 }

作为最后一点,我想指出您对初始化程序的命名约定并不是那么好。一个更合适和可读的将是

-(id)initWithFirstName:(NSString *)fName lastName:(NSString *)lName dateOfBirth:(NSDate *) dob;

【讨论】:

  • 非常感谢您的解释。命名约定只是为了对代码进行测试。否则更具描述性。我不明白为什么你声明 -(id)initWithNameAndDob 然后你做 +(XYZPerson *)WithNameAndDob?它们都将在 .m 文件中。
  • 在您的 .h 中,您(可以)同时拥有 initWith... 和 personWith 声明。两者的实现都在 .m 文件中。还要检查我的更新答案,因为我发现您的代码中有一个大错误并且我的签名中有一些错字;)
  • :哦,最大的错误是什么?!我假设您使用“可以”这个词意味着它不是必须的,所以我可以使用 initWith?
  • Objective-C 工厂方法只是alloc 和init 的包装,所以它应该返回相同的类型,id。方法的名称应该以要返回的对象的描述开头,因此在这种情况下,方法的名称应该类似于+personWithFirstName:lastName:dateOfBirth。请注意,方法名称应以小写字母开头,并且通常应避免包含缩写。正式的首字母缩写词(例如 HTML)是可以接受的,但应正确大写。
  • 编译器会知道类型,它可以帮助你在编译时捕获错误。将id 用于init 是必要的“解决方法”,而不是理想的功能。
【解决方案2】:

Gabriele Petronella 的解释很好,但有问题。

+(instancetype)personWithNameAndDob:(NSString *)fName last:(NSString *)lName birth:(NSDate *) dob {
return [[XYZPerson alloc] initWithNameAndDob:fName last:lName birth:dob];
}

It should be replaced with 
+(instancetype)personWithNameAndDob:(NSString *)fName last:(NSString *)lName birth:(NSDate *) dob {
return [[self alloc] initWithNameAndDob:fName last:lName birth:dob];
}

规则: 不要用名字来引用你自己的类,因为你不知道具体的类是什么。您会无意中切断通过子类化扩展和覆盖类的能力。反而, 在类的工厂方法中分配实例:[self alloc] 参考: http://qualitycoding.org/factory-method/

【讨论】:

  • i.AsifNoor 是正确的。在示例中,如果您不使用 self ,那么您的 XYZShoutingPerson 将无法正常工作。
猜你喜欢
  • 1970-01-01
  • 2020-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多