Swift对象初始化(类工厂方法,默认初始化,便利初始化)

5

我正在尝试找出在Swift中处理对象的最佳模式。

我认为使用初始化程序,包括方便和默认的初始化程序,是正确的...但是类工厂方法该怎么办呢?

我尝试创建一个简单的Person类和一个子类Student,其中包含一些属性和方法。这是最正确的方法吗?

   class Person{
    
    var _name: String
    var _surname: String
    var _dateOfBirthday: String
    var _phoneNumb: [String]
    
    init(name:String, surname:String, dateOfBirthday:String, phone:[String]){
        self._name = name
        self._surname = surname
        self._dateOfBirthday = dateOfBirthday
        self._phoneNumb = phone
    }
    
    convenience init() {
        self.init(name:"",surname:"",dateOfBirthday:"", phone:[])
    }
    
    convenience init(name:String){
        self.init(name:name,surname:"",dateOfBirthday:"", phone:[])
    }
    
    
}



class Student:Person{
    
    var _studentId:Int
    
    init(name: String, surname: String, dateOfBirthday: String, phone: [String], id:Int) {
        self._studentId = id
        super.init(name: "", surname: "", dateOfBirthday: "", phone: [])
    }
    
    convenience init(){
        self.init(name: "", surname: "", dateOfBirthday: "", phone: [], id:0)
    }
    
    convenience init(name:String){
        self.init(name:name,surname:"",dateOfBirthday:"", phone:[], id:0)
    }
    
}

如果我想添加一个类工厂方法,应该怎么做?是像这样吗,还是我做错了?

class func Person() -> Person {
 var x = Person()
 x._telephoneNumber = [String]() // is this needed? or i can initialize it later?
 return x
}

class func PersonWithName(name:String) -> Person {
 var x = Person(name:name, surname:"", dateOfBirthday:"", telephoneNumber:[])
 return x
}

这个正确吗?为什么使用init比使用类工厂更好呢?

2个回答

5
这样做正确吗?为什么使用init比类工厂更好?
如果可以使用init,为什么要创建“类工厂”?在Swift中,init是创建类的新对象的惯用方式。
在大多数情况下,添加方便的初始化程序是正确的选择,当您想要将快捷方式添加到类的主(指定)初始化程序时。但是,在您的情况下,它们是完全不必要的,因为Swift支持默认参数值。
只需像这样定义您的初始化程序:
init(name:String = "", surname:String = "", dateOfBirthday:String = "", phone:[String] = []) { ... }

这样,你可以用Person()Person(name: "Andrew")的方式调用它,也可以使用其他参数组合。

编辑:

顺便提一句,用下划线前缀实例变量似乎不是Swift惯用语法。省略下划线并使用self.来区分局部变量和实例变量是可以的:

self.name = name
self.surname = surname
self.dateOfBirthday = dateOfBirthday
self.phoneNumb = phone

那么在Swift中什么情况下会使用类工厂呢?几乎从不使用? - Swifterino
是的,基本上是这样。可能会有一些边缘情况需要使用其他方法,但我现在想不到任何情况。只需使用init即可。 - radex
当对象在运行时确定时怎么办?工厂和抽象工厂是相当标准的面向对象设计模式。我甚至不会提到依赖注入和广泛使用的类簇模式。(请参见https://dev59.com/nGAg5IYBdhLWcg3wDHfS) - Max MacLeod
2
其中一个问题是调用 Person() 并不能告诉你对象的配置情况。假设我想要一个初始化器为 person 设置随机年龄,因此不需要参数。就像 Objective-C 中的 PersonWithRandomAge。在 Swift 中该怎么做呢? - mattsson

0
在最近的Xcode 6.1和Swift 1.1之前,如果构建可能失败,就必须使用工厂模式,因为init()不能返回可选项。这也是为什么许多cocoa/objective-c库导入了工厂方法的原因。
随着Xcode 6.1和Swift 1.1的发布以及支持可以返回可选项的init(),您应该使用具有方便初始化程序的init()模式。在此版本中,Apple还更改了他们的cocoa/objective-c导入,以使用init() -> T?模式而不是工厂方法。
请参阅https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc6_release_notes.html获取发行说明。

这是正确的,尽管在 OP 的问题上下文中没有可失败的初始化程序,因此不相关。 - radex
“init() 可以返回可选项”是什么意思?我认为在 Swift 中,初始化程序不会返回值(与 Objective-C 不同)。 - Nicolas Miari
@NicolasMiari 这意味着“构造可能失败”。之所以在其他一些语言中使用类工厂是因为构造不能失败。随着Swift 1.1的推出,苹果引入了“可失败初始化程序”(写作init() -> T?)。这实际上意味着在Swift中您永远不需要工厂。 - tng
哦,我错过了那个!谢谢你澄清! - Nicolas Miari

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接