Programing

빠르고 명시적인 예제에서 편의성 init와 init의 차이점은 무엇입니까?

즐거운 cyworld 2021. 1. 10. 16:47
반응형

빠르고 명시적인 예제에서 편의성 init와 init의 차이점은 무엇입니까?


둘 다의 차이점 또는 편의 초기화의 목적을 이해하는 데 어려움이 있습니다. 감사


표준 init:

지정된 이니셜 라이저는 클래스의 기본 이니셜 라이저입니다. 지정된 이니셜 라이저는 해당 클래스에 의해 도입 된 모든 속성을 완전히 초기화하고 적절한 수퍼 클래스 이니셜 라이저를 호출하여 수퍼 클래스 체인까지 초기화 프로세스를 계속합니다.

convenience init:

편의 이니셜 라이저는 보조 이니셜 라이저로 클래스에 대한 이니셜 라이저를 지원합니다. 지정된 이니셜 라이저의 일부 매개 변수를 기본값으로 설정하여 편의 이니셜 라이저와 동일한 클래스에서 지정된 이니셜 라이저를 호출하도록 편의 이니셜 라이저를 정의 할 수 있습니다. 또한 편의 이니셜 라이저를 정의하여 특정 사용 사례 또는 입력 값 유형에 대한 해당 클래스의 인스턴스를 만들 수 있습니다.

당과 같은 스위프트 문서

기본적으로이 모든 것은 간단히 말해서 편리한 이니셜 라이저를 사용하여 지정된 이니셜 라이저를 더 빠르고 "편리하게"호출 할 수 있다는 것을 의미합니다. 따라서 편의 이니셜 라이저 는 지정된 이니셜 라이저의 재정의에서 볼 수 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)
}

주로 기본값을 가진 긴 이니셜 라이저와 함께 커스텀 뷰를 만들 때 많이 사용합니다. 문서는 내가 할 수있는 것보다 더 잘 설명하고 있습니다. 확인해보세요!


편의 이니셜 라이저는 속성이 많은 클래스가있는 경우 항상 모든 변수로 위트를 초기화하는 것이 "고통 스럽습니다". 따라서 편의 이니셜 라이저로 수행하는 작업은 일부 변수를 전달하여 초기화하는 것입니다. 개체, 나머지는 기본값으로 할당합니다. Ray Wenderlich 웹 사이트에는 유료 계정이 있기 때문에 무료인지 아닌지 확신 할 수없는 아주 좋은 비디오가 있습니다. 다음은 모든 변수를 사용하여 내 개체를 초기화하는 대신 제목을 지정하는 대신 확인할 수있는 예입니다.

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

다음은 Apple 개발자 포털 에서 가져온 간단한 예 입니다.

기본적으로 지정된 이니셜 라이저는이며 init(name: String)저장된 모든 속성이 초기화되도록합니다.

init()편의 이니셜, 인수를 복용하지를 automaticly 값 설정 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 개발자 포털 에서 선택 사항 및 상속에 대해 자세히 읽어 보는 것이 좋습니다 .


참고 : 전체 텍스트 읽기

지정된 이니셜 라이저는 클래스의 기본 이니셜 라이저입니다. 지정된 이니셜 라이저는 해당 클래스에 의해 도입 된 모든 속성을 완전히 초기화하고 적절한 수퍼 클래스 이니셜 라이저를 호출하여 수퍼 클래스 체인까지 초기화 프로세스를 계속합니다.

편의 이니셜 라이저는 보조 이니셜 라이저로 클래스에 대한 이니셜 라이저를 지원합니다. 지정된 이니셜 라이저의 일부 매개 변수를 기본값으로 설정하여 편의 이니셜 라이저와 동일한 클래스에서 지정된 이니셜 라이저를 호출하도록 편의 이니셜 라이저를 정의 할 수 있습니다.

클래스에 지정된 이니셜 라이저는 값 유형에 대한 단순 이니셜 라이저와 동일한 방식으로 작성됩니다.

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”

The init(name: String) initializer from the Food class is provided as a designated initializer because it ensures that all stored properties of a new Food instance are fully initialized. The Food class does not have a superclass, and so the init(name: String) initializer does not need to call super.init() to complete its initialization.

“The Food class also provides a convenience initializer, init(), with no arguments. The init() initializer provides a default placeholder name for a new food by delegating across to the Food class’s init(name: String) with a name value of [Unnamed]:”

“let mysteryMeat = Food()
// mysteryMeat's name is "[Unnamed]”

The second class in the hierarchy is a subclass of Food called RecipeIngredient. The RecipeIngredient class models an ingredient in a cooking recipe. It introduces an Int property called quantity (in addition to the name property it inherits from Food) and defines two initializers for creating RecipeIngredient instances:

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)
}
}

The RecipeIngredient class has a single designated initializer, init(name: String, quantity: Int), which can be used to populate all of the properties of a new RecipeIngredient instance. This initializer starts by assigning the passed quantity argument to the quantity property, which is the only new property introduced by RecipeIngredient. After doing so, the initializer delegates up to the init(name: String) initializer of the Food class.

page:536 Excerpt From: Apple Inc. “The Swift Programming Language (Swift 4).” iBooks. https://itunes.apple.com/pk/book/the-swift-programming-language-swift-4-0-3/id881256329?mt=11


So it comes in handy when you don't need to specify each and every property for a class. So for instance, if I want to create all adventures with starting HP value of 100, I would use this following convenience init and just add in a name. This is going to cut down on the code a lot.

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)
    }
}

A convenience initializer can be defined in a class extension. But a standard one - can not.


Where convenience initializers beat setting default parameter values

For me, convenience initializers are useful if there is more to do than simply set a default value for a class property.

Class implementation with designated init()

Otherwise, I would simply set the default value in the init definition, e.g.:

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
    }
}

Class extension with convenience init()

However, there might be more to do than simply set a default value, and that is where convenience initializers come in handy:

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)
    }
}

Usage examples

// 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")

ReferenceURL : https://stackoverflow.com/questions/40093484/what-is-the-difference-between-convenience-init-vs-init-in-swift-explicit-examp

반응형