web-dev-qa-db-ja.com

Swiftの便利なinitとinitの違いは何ですか?

両者の違い、または便宜上の初期化の目的を理解するのに苦労しています。ありがとう

53
Chino Pan

標準init

指定された初期化子は、クラスの主要な初期化子です。指定されたイニシャライザは、そのクラスによって導入されたすべてのプロパティを完全に初期化し、適切なスーパークラスイニシャライザを呼び出して、スーパークラスチェーンまでの初期化プロセスを続行します。

convenience init

便利な初期化子はセカンダリであり、クラスの初期化子をサポートします。便利なイニシャライザを定義して、指定されたイニシャライザのパラメータの一部をデフォルト値に設定して、便利なイニシャライザと同じクラスから指定されたイニシャライザを呼び出すことができます。また、特定のユースケースまたは入力値タイプ用にそのクラスのインスタンスを作成するための便利な初期化子を定義することもできます。

Swift Documentation

基本的にこれは、簡単に言えば、便利なイニシャライザーを使用して、指定されたイニシャライザーをより速く、より便利に呼び出すことです。したがって、便利なイニシャライザーでは、指定されたイニシャライザーのオーバーライドで表示されるself.initのようなものの代わりにsuper.initを使用する必要があります。

擬似コードの例:

init(param1, param2, param3, ... , paramN) {
     // code
}

// can call this initializer and only enter one parameter,
// set the rest as defaults
convenience init(myParamN) {
     self.init(defaultParam1, defaultParam2, defaultParam3, ... , myParamN)
}

主にデフォルトを持つ長い初期化子を使用してカスタムビューなどを作成するときに、これらを頻繁に使用します。ドキュメントは私が説明できるよりも良い説明をします、チェックしてください!

75
treyhakanson

便利な初期化子は、常にすべての変数でウィットを初期化する「痛みを伴う」ようなプロパティを持つクラスがある場合に使用されます。そのため、便利な初期化子で行うことは、オブジェクトを作成し、残りにデフォルト値を割り当てます。レイウェンダリッヒのウェブサイトには非常に優れたビデオがありますが、有料アカウントを持っているので無料かどうかはわかりません。ここに、すべての変数Imでオブジェクトを初期化する代わりに、単にタイトルを付けるだけであることがわかる例を示します。

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
49

Apple Developer portal から取られた簡単な例です。

基本的に、指定された初期化子はinit(name: String)であり、保存されているすべてのプロパティが初期化されるようにします。

引数をとらないinit()簡易イニシャライザーは、指定されたイニシャライザーを使用して、name格納プロパティの値を[Unnamed]に自動的に設定します。

class Food {
    let name: String

    // MARK: - designated initializer
    init(name: String) {
        self.name = name
    }

    // MARK: - convenience initializer
    convenience init() {
        self.init(name: "[Unnamed]")
    }
}

// MARK: - Examples
let food = Food(name: "Cheese") // name will be "Cheese"
let food = Food()               // name will be "[Unnamed]"

少なくともいくつかのプロパティが保存されている大きなクラスを扱う場合に便利です。 Apple Developer portal。 でオプションと継承についてさらに読むことをお勧めします

11
dirtydanee

注:テキスト全体を読む

指定された初期化子は、クラスの主要な初期化子です。指定された初期化子は、そのクラスによって導入されたすべてのプロパティを完全に初期化し、適切なスーパークラス初期化子を呼び出して、スーパークラスチェーンまで初期化プロセスを続行します。

便利な初期化子はセカンダリであり、クラスの初期化子をサポートします。便利なイニシャライザを定義して、指定されたイニシャライザのパラメータの一部をデフォルトに設定して、便利なイニシャライザと同じクラスから指定されたイニシャライザを呼び出すことができます。

クラスの指定された初期化子は、値型の単純な初期化子と同じ方法で記述されます。

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]であるFoodクラスのinit(name:String)に委任することにより、新しい食品のデフォルトのプレースホルダー名を提供します。

“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)初期化子まで委任します。

ページ:536抜粋:Apple Inc.「Swiftプログラミング言語(Swift 4)。」iBooks。 https://iTunes.Apple.com/pk/book/the-Swift-programming-language-Swift-4-0-3/id881256329?mt=11

2
Abuzar Manzoor

したがって、クラスのすべてのプロパティを指定する必要がない場合に便利です。たとえば、HPの開始値が100のすべてのアドベンチャーを作成する場合、次のconvenience 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)
    }
}
2
Nirav

便利な初期化子がデフォルトのパラメーター値の設定に勝る場所

私にとって、convenience initializersは、クラスプロパティにデフォルト値を設定するだけでなく、もっとやることがある場合に役立ちます。

指定されたinit()を使用したクラス実装

それ以外の場合は、単にinit定義にデフォルト値を設定します。例:

class Animal {

    var race: String // enum might be better but I am using string for simplicity
    var name: String
    var legCount: Int

    init(race: String = "Dog", name: String, legCount: Int = 4) {
        self.race = race
        self.name = name
        self.legCount = legCount // will be 4 by default
    }
}

便利なinit()を使用したクラス拡張

ただし、単にデフォルト値を設定するだけでなく、それ以外のことも必要になる場合があります。その場合は、convenience initializersが役立ちます。

extension Animal {
    convenience init(race: String, name: String) {
        var legs: Int

        if race == "Dog" {
            legs = 4
        } else if race == "Spider" {
            legs = 8
        } else {
            fatalError("Race \(race) needs to be implemented!!")
        }

        // will initialize legCount automatically with correct number of legs if race is implemented
        self.init(race: race, name: name, legCount: legs)
    }
}

使用例

// default init with all default values used
let myFirstDog = Animal(name: "Bello")

// convenience init for Spider as race
let mySpider = Animal(race: "Spider", name: "Itzy")

// default init with all parameters set by user
let myOctopus = Animal(race: "Octopus", name: "Octocat", legCount: 16)

// convenience init with Fatal error: Race AlienSpecies needs to be implemented!!
let myFault = Animal(race: "AlienSpecies", name: "HelloEarth")
0
Chris Graf