스위프트 문법 17(Initializer)

스위프트 문법 17(Initializer)

- 8 mins

Initializer

Init

아래 예제를 보면 height, xPosition변수가 초기화가 되어있지않아 오류가 난다

class Rectangle {
  var value: String?
  var width: Int = 20
  var height: Int 
  var xPosition: Int
}

해결하는 방법

  1. 초기값을 넣어준다.
    class Rectangle {
      var value: String?
      var width: Int = 20
      var height: Int = 0
      var xPosition: Int = 0
    }
    
  2. 옵셔널을 이용한다.
    class Rectangle {
      var value: String?
      var width: Int = 20
      var height: Int?
      var xPosition: Int?
    }
    
  3. init()함수를 이용해서 초기화 한다.
    class Rectangle {
      var value: String?
      var width: Int = 20
      var height: Int 
      var xPosition: Int
      init() {
     height = 10
     xPosition = 5
      }
      init(height: Int, xPosition: Int) {
     self.height = height
     self.xPosition = xPosition  
      }
    }
    

Designated Initializer

Convenience Initializer

class Rectangle1 {
  var value: String?
  var width: Int = 20
  var height: Int
  var xPosition: Int
  
  init(height: Int, xPosition: Int) {
    self.height = height
    self.xPosition = xPosition
  }
  
  // 일부 값만을 파라미터로 받을 때
  convenience init(height: Int) {             //<----여기
    self.init(height: height, xPosition: 10)
    // 자기 자신의 초기화 메서드 호출
  }
  
//  convenience init(height: Int) {     //변수가 많을때 하나만 파라미터로 값을 받고 나머지는 설정해줄때 유용함
//    self.init()
//    self.height = height
//  }
  
  //이건 조금 아래에서 배울 Failable Initializer이다.
  init?(_ height: Int, _ xPosition: Int) {
    guard height > 0 else { return nil } //이 조건에 의해 height가 0보다 작으면 nil이 나옴
    self.height = height
    self.xPosition = xPosition
  }
}

let rect = Rectangle1(height: 20) //자동으로 convenience로 초기화됨

Failable Initializer


초기화 과정은 Convenience -> Convenience -> … -> Designated (최종) 순서로 동작


Super-Class Init

//부모 클래스
class Base {
  var value: String
  var someProperty: String
  
  init() {
    value = "Base"
    someProperty = "someProperty"
  }
  
  // Designated Initializer 가 하나일 때는 서브 클래스에서 수퍼클래스의 초기화 함수를 부르지 않아도 동작
  // 여러 개로 만들 경우 어떤 초기화 메서드를 선택해야 할지 알 수 없으므로 선택해주지 않으면 에러 발생
  // 이 때는, 서브 클래스의 모든 Designated Initializer 마다 수퍼 클래스의 초기화 함수를 명시적으로 선택해주어야 함.
  // Convenience 는 달라질 거 없음 -> 
  
//  init(_ value: String) {
//    self.value = value
//    self.someProperty = "someProperty"
//  }
  
  convenience init(someProperty: String) {
    self.init()
    self.someProperty = someProperty
  }
}

//자식 클래스
class Rectangle: Base {
  var width: Int = 20
  var height: Int
  var xPosition: Int
  
  override init() {
    height = 10
    xPosition = 5
  }
  
  init(height: Int, xPosition: Int) {
    self.height = height
    self.xPosition = xPosition
  }
  
  convenience init(height: Int) {
    self.init(height: height, xPosition: 10)
  }
}

또 다른 예제

class Shape {
    var name: String
    var sides : Int
    init(sides:Int, named: String) {
        self.sides = sides
        self.name = named
        printShapeDescription()
    }
    func printShapeDescription() {
        print("Shape Name :\(self.name)")
        print("Sides :\(self.sides)")
    }
}

class Triangle: Shape {
    var hypotenuse: Int
    init(hypotenuse:Int) {
        self.hypotenuse = hypotenuse
        super.init(sides: 3, named: "Triangle")
    }
    
    override func printShapeDescription() {
        super.printShapeDescription()
        print("Hypotenuse :\(self.hypotenuse)")
    }
}

let triangle = Triangle(hypotenuse: 12)

//Shape Name :Triangle
//Sides :3
//Hypotenuse :12

Initializer 의 다른 특징들

초기화 이전 단계에서 인스턴스 메서드 호출 불가

다른 메서드 호출 중 초기화 되지 않은 프로퍼티를 사용할 수도 있기 때문에 컴파일 에러 발생

init(height: Int, xPosition: Int) {
  self.height = height
  someMethod()          // 초기화가 끝나지 않았기 때문에 Error 발생
  self.xPosition = xPosition
}

fun someMethod() {
  print(self.height)
}


Extension(수평) Initializer

Extension에서는 Convenience Initializer 는 추가할 수 있어도 Designated Initializer 는 할 수 없음

class Rectangle {
  var height: Int
  var xPosition: Int
  
  init(height: Int, xPosition: Int) {
    self.height = height
    self.xPosition = xPosition
  }
}

//Extension으로 기능 추가
extension Rectangle {
//  // 에러 발생
//  init(height: Int, xPosition: Int) {
//    self.height = height
//    self.xPosition = xPosition
//  }
  
  // Convenience 는 가능하다.
  convenience init(height: Int) {
    self.init(height: height, xPosition: 10)
  }
}


Required Initializer

상속받은 클래스에서 반드시 작성해주어야 하는 초기화 메서드가 있을 때 required 키워드 사용 이 경우 서브 클래스에서는 해당 초기화 메서드를 반드시 작성해주어야 하며, override 키워드는 생략 가능

required init(height: Int, xPosition: Int) {
  self.height = height
  self.xPosition = xPosition
}


Deinitializer

할당된 객체가 해제될 때는 deinit 메소드가 호출됨.

deinit {
  // 객체 메모리 해제 시 동작할 코드
}
comments powered by Disqus
rss facebook twitter github youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora quora