init()
Objective C のように値を返さないため-init
、ファクトリ メソッドを使用するのが最も簡単なオプションのようです。
private
1 つのトリックは、次のようにイニシャライザを としてマークすることです。
class Person : CustomStringConvertible {
static func person(age: UInt) -> Person {
if age < 18 {
return ChildPerson(age)
}
else {
return AdultPerson(age)
}
}
let age: UInt
var description: String { return "" }
private init(_ age: UInt) {
self.age = age
}
}
extension Person {
class ChildPerson : Person {
let toyCount: UInt
private override init(_ age: UInt) {
self.toyCount = 5
super.init(age)
}
override var description: String {
return "\(self.dynamicType): I'm \(age). I have \(toyCount) toys!"
}
}
class AdultPerson : Person {
let beerCount: UInt
private override init(_ age: UInt) {
self.beerCount = 99
super.init(age)
}
override var description: String {
return "\(self.dynamicType): I'm \(age). I have \(beerCount) beers!"
}
}
}
これにより、次の動作が発生します。
Person.person(10) // "ChildPerson: I'm 10. I have 5 toys!"
Person.person(35) // "AdultPerson: I'm 35. I have 99 beers!"
Person(35) // 'Person' cannot be constructed because it has no accessible initializers
Person.ChildPerson(35) // 'Person.ChildPerson' cannot be constructed because it has no accessible initializers
すべてのサブクラスを同じソースファイルに実装する必要があることを意味するため、Objective C ほど良くはありません。また、単純な ではなくprivate
、わずかな構文の違いPerson.person(x)
(またはその他) がありますが、実際には同じように機能します。Person.create(x)
Person(x)
として文字通りインスタンス化できるようにするには、実際の基本クラスのプライベート インスタンスを含み、すべてをそれに転送するプロキシ クラスにするPerson(x)
ことができます。Person
メッセージ転送がなければ、これはプロパティ/メソッドがほとんどない単純なインターフェースでは機能しますが、より複雑なものでは扱いにくくなります:P