両方の違い、または の目的を理解するのに苦労していconvenience init
ます。
10 に答える
便利な初期化子は、多くのプロパティを持つクラスがあり、そのすべての変数で常にウィットを初期化するのが一種の「苦痛」になる場合に使用されます。そのため、便利な初期化子で行うことは、いくつかの変数を渡してオブジェクトを作成し、残りにデフォルト値を割り当てます。Ray Wenderlich の Web サイトに非常に優れたビデオがありますが、有料アカウントを持っているため、無料かどうかはわかりません。これは、オブジェクトをすべての変数で初期化するのではなく、単にタイトルを付けただけであることがわかる例です。
struct Scene {
var minutes = 0
}
class Movie {
var title: String
var author: String
var date: Int
var scenes: [Scene]
init(title: String, author: String, date: Int) {
self.title = title
self.author = author
self.date = date
scenes = [Scene]()
}
convenience init(title:String) {
self.init(title:title, author: "Unknown", date:2016)
}
func addPage(page: Scene) {
scenes.append(page)
}
}
var myMovie = Movie(title: "my title") // Using convenicence initializer
var otherMovie = Movie(title: "My Title", author: "My Author", date: 12) // Using a long normal initializer
注: テキスト全体を読む
指定された初期化子は、クラスの主要な初期化子です。指定された初期化子は、そのクラスによって導入されたすべてのプロパティを完全に初期化し、適切なスーパークラス初期化子を呼び出して、初期化プロセスをスーパークラス チェーンまで続行します。
便利な初期化子は二次的なもので、クラスの初期化子をサポートします。便利な初期化子を定義して、指定された初期化子のパラメーターの一部がデフォルトに設定されている便利な初期化子と同じクラスから指定された初期化子を呼び出すことができます。
クラスの指定された初期化子は、値型の単純な初期化子と同じ方法で記述されます。
init(parameters) {
statements
}
コンビニエンス イニシャライザは同じスタイルで記述されますが、 init キーワードの前にスペースで区切ってコンビニエンス修飾子を配置します。
convenience init(parameters) {
statements
}
実際の例は次のとおりです。
class Food {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[Unnamed]")
}
}
let namedMeat = Food(name: "Bacon")
// namedMeat's name is "Bacon”
Food クラスの init(name: String) イニシャライザは、指定されたイニシャライザとして提供されます。これは、新しい Food インスタンスの格納されたすべてのプロパティが完全に初期化されることを保証するためです。Food クラスにはスーパークラスがないため、init(name: String) 初期化子はその初期化を完了するために super.init() を呼び出す必要はありません。
「Food クラスは、引数のない便利な初期化子 init() も提供します。init() イニシャライザは、[Unnamed] の name 値を使用して Food クラスの init(name: String) に委譲することにより、新しい食品のデフォルトのプレースホルダ名を提供します:"</p>
“let mysteryMeat = Food()
// mysteryMeat's name is "[Unnamed]”
階層の 2 番目のクラスは、RecipeIngredient という Food のサブクラスです。RecipeIngredient クラスは、料理レシピの材料をモデル化します。これは、(Food から継承する name プロパティに加えて) quantity と呼ばれる Int プロパティを導入し、RecipeIngredient インスタンスを作成するための 2 つの初期化子を定義します。
class RecipeIngredient: Food {
var quantity: Int
init(name: String, quantity: Int) {
self.quantity = quantity
super.init(name: name)
}
override convenience init(name: String) {
self.init(name: name, quantity: 1)
}
}
RecipeIngredient クラスには、指定された単一の初期化子 init(name: String, quantity: Int) があり、これを使用して、新しい RecipeIngredient インスタンスのすべてのプロパティを設定できます。この初期化子は、渡された数量引数を数量プロパティに割り当てることから始めます。これは、RecipeIngredient によって導入された唯一の新しいプロパティです。その後、初期化子は Food クラスの init(name: String) 初期化子に委譲します。
page:536 抜粋: Apple Inc.「The Swift Programming Language (Swift 4)」。アイブック。https://itunes.apple.com/pk/book/the-swift-programming-language-swift-4-0-3/id881256329?mt=11
したがって、クラスのすべてのプロパティを指定する必要がない場合に便利です。たとえば、最初の HP 値が 100 のすべてのアドベンチャーを作成したい場合は、次の便利な initを使用して、名前を追加するだけです。これにより、コードが大幅に削減されます。
class Adventure {
// Instance Properties
var name: String
var hp: Int
let maxHealth: Int = 100
// Optionals
var specialMove: String?
init(name: String, hp: Int) {
self.name = name
self.hp = hp
}
convenience init(name: String){
self.init(name: name, hp: 100)
}
}
すべての答えは良さそうですが、簡単な例で理解しましょう
class X{
var temp1
init(a: Int){
self.temp1 = a
}
これで、クラスが別のクラスを継承できることがわかりました。
class Z: X{
var temp2
init(a: Int, b: Int){
self.temp2 = b
super.init(a: a)
}
この場合、クラス Z のインスタンスを作成するときに、値「a」と「b」の両方を指定する必要があります。
let z = Z(a: 1, b: 2)
ただし、b の値のみを渡し、残りの値を他の値のデフォルト値にしたい場合は、他の値をデフォルト値に初期化する必要があります。しかし、どうやって待ってください?、そのためには、クラスでのみ事前に設定する必要があります。
//This is inside the class Z, so consider it inside class Z's declaration
convenience init(b: Int){
self.init(a: 0, b: b)
}
convenience init(){
self.init(a: 0, b: 0)
}
これで、変数に値の一部、すべて、または値を指定せずに、クラス Z のインスタンスを作成できます。
let z1 = Z(b: 2)
let z2 = Z()