둘 다의 차이점 또는 .NET Framework의 목적을 이해하는 데 어려움이 convenience init
있습니다.
둘 다의 차이점 또는 .NET Framework의 목적을 이해하는 데 어려움이 convenience 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 개발자 포털 에서 선택 사항 및 상속에 대해 자세히 읽어 보는 것이 좋습니다 .
나를 위해, convenience initializers
단순히 클래스 속성에 대한 기본값을 설정하는 것보다 더 많은 일 이 있다면 유용합니다.
그렇지 않으면 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
}
}
그러나 단순히 기본값을 설정하는 것보다 더 할 일이있을 수 있으며, 이것이 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")
편의 이니셜 라이저는 클래스 확장 에서 정의 할 수 있습니다 . 그러나 표준적인 것은 할 수 없습니다.
참고 : 전체 텍스트 읽기
지정된 이니셜 라이저는 클래스의 기본 이니셜 라이저입니다. 지정된 이니셜 라이저는 해당 클래스에 의해 도입 된 모든 속성을 완전히 초기화하고 적절한 수퍼 클래스 이니셜 라이저를 호출하여 수퍼 클래스 체인까지 초기화 프로세스를 계속합니다.
편의 이니셜 라이저는 보조 이니셜 라이저로 클래스에 대한 이니셜 라이저를 지원합니다. 지정된 이니셜 라이저의 매개 변수 중 일부를 기본값으로 설정하여 편의 이니셜 라이저와 동일한 클래스에서 지정된 이니셜 라이저를 호출하도록 편의 이니셜 라이저를 정의 할 수 있습니다.
클래스에 지정된 이니셜 라이저는 값 유형에 대한 간단한 이니셜 라이저와 동일한 방식으로 작성됩니다.
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]”
계층 구조의 두 번째 클래스는 RecipeIngredient라는 Food의 하위 클래스입니다. RecipeIngredient 클래스는 요리 레시피의 재료를 모델링합니다. 이는 Quantity라는 Int 속성 (Food에서 상속되는 이름 속성 외에)을 도입하고 RecipeIngredient 인스턴스를 만들기위한 두 개의 이니셜 라이저를 정의합니다.
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 클래스에는 새로운 RecipeIngredient 인스턴스의 모든 속성을 채우는 데 사용할 수있는 init (name : String, quantity : Int)라는 단일 지정된 이니셜 라이저가 있습니다. 이 이니셜 라이저는 전달 된 수량 인수를 수량 속성에 할당하여 시작합니다.이 속성은 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
따라서 클래스에 대한 모든 속성을 지정할 필요가 없을 때 유용합니다. 예를 들어 시작 HP 값이 100 인 모든 모험을 만들고 싶다면 다음과 같은 편의 초기화를 사용 하고 이름 만 추가하면됩니다. 이것은 코드를 많이 줄일 것입니다.
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 Player {
let name: String
let level: Int
init(name: String, level: Int) {
self.name = name
self.level = level
}
init(name: String) {
self.init(name: name, level: 0) //<- Call the initializer above?
//Sorry you can't do that. How about adding a convenience keyword?
}
}
Player(name:"LoseALot")
편의 키워드로
class Player {
let name: String
let level: Int
init(name: String, level: Int) {
self.name = name
self.level = level
}
//Add the convenience keyword
convenience init(name: String) {
self.init(name: name, level: 0) //Yes! I am now allowed to call my fellow initializer!
}
}
모든 대답은 좋은 것 같지만 간단한 예를 들어 이해하겠습니다.
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의 값만 전달하고 나머지는 다른 값을 기본값으로 사용하려면 어떻게해야할까요?이 경우 다른 값을 기본값으로 초기화해야합니다. 그러나 어떻게 기다려?, U는 수업 전에 그것을 잘 설정해야합니다.
//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()