티스토리 뷰

Swift는 선언하는 시점에 프로퍼티들이 초기화가 되어 있어야 합니다.

Java처럼 시스템에서 자동으로 하여주지 않기 때문에 초기값을 지정하여 주어야 하는데요.

 

초기값을 지정하여 주거나 혹은 Initializer를 통해서 초기화를 진행하여 주어야 합니다.

( 예외적으로 ! (느낌표) 를 사용하여 초기화를 조금 나중에 하여 주어도 되긴 합니다. 기본적으로는 옵셔널이며 nil값을 가지고 있습니다. )

 

그냥 초기값을 넣어주는것은 알겠고 Initializer에 대해서 알아봅시다.

 

1. Designated Initializer

 

클래스에 반드시 1개 이상이 필요하며, 모든 프로퍼티를 단독으로 전체 초기화가 가능하게 되어 있는 Initializer입니다.

무슨말이냐면

class Person {
  var name: String
  var age: Int?
  var address: String
  
  init() {
    name = "DH"
    address = "서울특별시"
  }

  init(name: String, address: String) {
    self.name = name
    self.address = address
  }
}

 

이렇게 단독으로 모든 부분들이 처리가 되는 선언자입니다.

 

2. Convenience Initializer

 

모든 프로퍼티를 단독으로 처리하지 않고 일부 프로퍼티만 초기화를 하여주고 다른 Initialization을 호출하여서 전체 초기화를 시켜주는 Initializer 입니다.

class Person {
  // 위에 선언한거 다 있는 상태입니다. Designated Initializer 는 다 있음
  
  convenience init(name: String) {
    self.init(name: name, address: "")
  }
  
  convenience init(address: String) {
    self.init()
    self.name = ""
  }
}

 

3. Failable Initializer

 

초기화에 필요한 파라메터들을 전달받고 만족하지 못할 경우에 nil로 처리할수 있습니다.

init?(name: String, address: String, age: Int) {
  guard age <= 100 else { return nil }
  
  self.name = name
  self.address = address
  self.age = age
}

 

4. 상속받을 경우의 초기화

 

당연한 이야기이지만 상속을 받아서 사용하는 경우에는 Initializer를 부모의 것도 처리를 하여 주어야 합니다.

그렇지 않을 경우에는 자신이 사용할수 있는 프로퍼티에 대해서 모두 초기화가 되지 않기 때문입니다.

 

그렇지만 예외가 한가지 존재하는데요.

Designated Initializer가 한개만 존재할 경우에는 별도로 따로 호출하여 줄 필요가 없다고 합니다.

그렇지 않으면 어떻게 초기화를 할 것인지를 지정하여 주어야 하는데요.

 

다음을 한번보면 이해가 될겁니다.

class Person {
  var name: String
  var age: Int?
  var address: String
  
  init() {
    name = "DH"
    address = "서울특별시"
  }

  init(name: String, address: String) {
    self.name = name
    self.address = address
  }
}

class EastPerson : Person {
  var school: String
  var money: Int

  override init() {
    school = "서울고등학교"
    money = 0
  }

  init(school: String) {
    self.school = school
    self.money = 0
  }

  init(money: Int) {
    self.init("No School")
    self.money = money
  }
}

모든 생성자에서 super를 호출한 흔적이없습니다.

 

그렇지 않고 생성자를 한개 더 호출하게 되면

Super.init isn't called on all paths before returning from initializer

이런 문구를 보게 됩니다.

한개라면 자동으로 알아서 처리를 해주겠지만 두개일 경우에는 안된다는 거죠.

 

이렇게 되었을 경우에 super를 호출하는 부분을 추가하여 주어야 하는데요.

class EastPerson : Person {
  var school: String
  var money: Int

  override init() {
    super.init() // Fail
    school = "서울고등학교"
    money = 0
  }

  init(school: String) {
    self.school = school
    self.money = 0
    super.init() // Okay
  }
}

위의 예제처럼 self를 모두 초기화 하고 난 이후에 super를 호출하여 주어야 합니다.

 

초기화중에는 인스턴스 function은 호출이 안되고 타입 function은 호출이 가능하다고 합니다.

init(name: String) {
  self.name = name
  someFunction() // Fail
  someFunction2() // Success
  self.address = "서울"
  
  someFunction() // Success
}

func someFunction() {
  // test
}

class func someFuntion2() {
  // test2
}

 

5. required init

required init(extra: String) {
  self.name = extra
  self.address = extra
}

말도 안되는 생성자 코드를 넣었지만. 상속후에 꼭 작성해주어야 하는 생성자는 required를 붙여주면 됩니다.

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함