Swift 이니셜라이저가 슈퍼클래스에서 편의 이니셜라이저를 호출할 수 없는 이유는 무엇입니까?
두 가지 클래스를 고려합니다.
class A {
var x: Int
init(x: Int) {
self.x = x
}
convenience init() {
self.init(x: 0)
}
}
class B: A {
init() {
super.init() // Error: Must call a designated initializer of the superclass 'A'
}
}
왜 이것이 허용되지 않는지 모르겠습니다.궁극적으로, 각 클래스의 지정된 이니셜라이저는 필요한 값과 함께 호출되는데, 왜 반복해야 합니까?B
의init
의 기본값을 지정하여x
다시, 형편이 좋을 때.init
에A
괜찮겠습니까?
이것은 스위프트 프로그래밍 가이드에 명시된 "이니셜라이저 체인" 규칙의 규칙 1로, 다음과 같습니다.
규칙 1: 지정된 이니셜라이저는 즉시 수퍼 클래스에서 지정된 이니셜라이저를 호출해야 합니다.
강조해주세요.지정된 이니셜라이저는 편의 이니셜라이저를 호출할 수 없습니다.
규칙과 함께 허용되는 초기화 "방향"을 보여주는 다이어그램이 있습니다.
고려하다
class A
{
var a: Int
var b: Int
init (a: Int, b: Int) {
print("Entering A.init(a,b)")
self.a = a; self.b = b
}
convenience init(a: Int) {
print("Entering A.init(a)")
self.init(a: a, b: 0)
}
convenience init() {
print("Entering A.init()")
self.init(a:0)
}
}
class B : A
{
var c: Int
override init(a: Int, b: Int)
{
print("Entering B.init(a,b)")
self.c = 0; super.init(a: a, b: b)
}
}
var b = B()
클래스 A의 지정된 모든 이니셜라이저는 재정의되므로 클래스 B는 A의 모든 편의 이니셜라이저를 상속합니다.이를 실행하면 출력됩니다.
Entering A.init()
Entering A.init(a:)
Entering B.init(a:,b:)
Entering A.init(a:,b:)
이제 지정된 이니셜라이저 B.init(a:b:)가 기본 클래스 편의 이니셜라이저 A.init(a:)를 호출할 수 있게 되면 B.init(a:,b:)에 대한 재귀 호출이 발생합니다.
왜냐하면 무한한 재귀로 끝날 수 있기 때문입니다.고려 사항:
class SuperClass {
init() {
}
convenience init(value: Int) {
// calls init() of the current class
// so init() for SubClass if the instance
// is a SubClass
self.init()
}
}
class SubClass : SuperClass {
override init() {
super.init(value: 10)
}
}
그리고 다음을 봅니다.
let a = SubClass()
전화가 올 것입니다.SubClass.init()
전화가 올 것입니다.SuperClass.init(value:)
전화가 올 것입니다.SubClass.init()
.
지정/편의성 init 규칙은 클래스 초기화가 항상 정확하도록 설계되었습니다.
저는 이것에 대한 해결책을 찾았습니다.슈퍼예쁘지는 않지만 슈퍼클래스의 값을 모르거나 기본값을 설정하고 싶어하는 문제를 해결해줍니다.
당신이 해야 할 일은 편의성을 이용하여 슈퍼 클래스의 인스턴스를 만드는 것입니다.init
바로 옆에init
하층 계급의그런 다음 당신은 지정된 사람에게 전화를 합니다.init
당신이 방금 만든 인스턴스를 사용하는 슈퍼의.
class A {
var x: Int
init(x: Int) {
self.x = x
}
convenience init() {
self.init(x: 0)
}
}
class B: A {
init() {
// calls A's convenience init, gets instance of A with default x value
let intermediate = A()
super.init(x: intermediate.x)
}
}
편리한 곳에서 초기화 코드를 추출하는 것을 고려해 보십시오.init()
새 도우미 기능으로foo()
,불러foo(...)
하위 클래스에서 초기화를 수행합니다.
이니셜라이저와 그 상속에 대한 자세한 설명은 WWDC-비디오 "403 Intermediate Swift"를 18시 30분에 보십시오.제가 이해한 바와 같이, 다음 사항을 고려해 보십시오.
class Dragon {
var legs: Int
var isFlying: Bool
init(legs: Int, isFlying: Bool) {
self.legs = legs
self.isFlying = isFlying
}
convenience initWyvern() {
self.init(legs: 2, isFlying: true)
}
}
그러나 이제 Wyrm-하위 클래스를 생각해 보십시오.Wyrm은 다리와 날개가 없는 용입니다.따라서 와이번의 이니셜라이저(2개의 다리, 2개의 날개)는 잘못된 것입니다!편리한 Wyvern-Initializer를 호출할 수 없고 지정된 전체 Initializer만 호출할 수 있는 경우 이러한 오류를 피할 수 있습니다.
class Wyrm: Dragon {
init() {
super.init(legs: 0, isFlying: false)
}
}
이니셜라이저 두 개, 즉 기본값이 있는 이니셜라이저 한 개를 사용하는 것이 어떻습니까?
class A {
var x: Int
init(x: Int) {
self.x = x
}
init() {
self.x = 0
}
}
class B: A {
override init() {
super.init()
// Do something else
}
}
let s = B()
s.x // 0
언급URL : https://stackoverflow.com/questions/24122421/why-cant-swift-initializers-call-convenience-initializers-on-their-superclass
'programing' 카테고리의 다른 글
요소를 이동하지 않고 호버에 CSS 테두리 추가 (0) | 2023.08.23 |
---|---|
HTML 태그(코드)를 ASP.net MVC & JQuery로 문자열로 게시합니다. (0) | 2023.08.23 |
NuoDB를 사용하여 Ruby On Rails에서 SQL 명령을 수동으로 실행하는 방법 (0) | 2023.08.23 |
SQL Server 로그인 오류: 'NT AUTHORITY\SYSTEM' 사용자에 대한 로그인 실패 (0) | 2023.08.23 |
AWS S3: POST 또는 PUT 요청을 사용하여 파일을 업로드해야 합니까? (0) | 2023.08.23 |