[Swift 문법] 인스턴스의 생성과 소멸

!·2022년 6월 26일
0

Swift 문법

목록 보기
17/27

이니셜 라이저

  • 이니셜라이저를 통해 초기값을 할당하거나, 기본값을 통해 프로퍼티를 초기화하는 경우, 프로퍼티감시자가 실행되지 않는다.
  • 스위프트모든 인스턴스는 초기화와 동시에 모든 프로퍼티에 유효한 값이 할당되어 있어야 한다.
  • 프로퍼티에 미리 기본값을 할당해두면, 인스턴스가 생성됨과 동시에 초기값을 지니게 된다.
  • 프로퍼티 기본값을 지정하기 어려운 경우에는 이니셜라이저를 통해 인스턴스가 가져야할 초기값을 전달할 수 있다.
  • cpp, java등의 생성자와 유사한 개념이다.
class PersonB{
	var name : String
    var age : Int
    var nickName : String
    
    // 이니셜라이저
    init(name: String, age: Int, nickName: String){
    	self.name = name
        self.age = age
        self.nickName = nickName
    }
}

let hana : PersonB = PersonB(name : "hana", age : 20, nickName : "하나")
let hana : PersonB = PersonB(name : "hana", age : 20, nickName : "") // 굳이 별명이 없는데 닉네임을 채워야할까?
// 프로퍼티의 초기값이 필요없을 때 옵셔널을 이용!
class PersonC{
	var name : String
    var age : Int
    var nickName : String?
    
    // 다른 이니셜라이저를 호출 : convenience 명시
    convenience init(name: String, age: Int, nickName: String){
    	self.init(name: String, age: Int)
        self.nickName = nickName
    }
    
    init(name: String, age: Int){
    	self.name = name
        self.age = age
    }
    
let jenny: PersonC = PersonC(name: "jenny", age: 10)
let mike: PersonC = PersonC(name: "mike", age: 10, nickName: "m")
// 암시적 추출 옵셔널은 인스턴스 사용에 꼭 필요하지만, 초기값을 할당하고자 하지 않을때 사용

class Puppy{
	var name: String 
    var owner: PersonC!
    	
    init(name: String){
    	self.name= name
    }
    
    func goOut(){
    	print("\(name)가 주인 \(owner.name)와 산책을 나갑니다.")
    }
}

let happy: Puppy = Puppy(name: "happy)
happy.goOut() // 런타임 에러! 
happy.owner = jenny
happy.goOut() // happy가 주인 jenny와 산책을 합니다.

옵셔널 프로퍼티

  • 이니셜라이저를 통해 초긱밧을 지정하고 싶지 않은 프로퍼티에는 옵셔널 타입으로 프로퍼티를 정의할 수 있다.
  • 이니셜라이저를 통해 초기값이 주어지지않은 옵셔널 프로퍼티는 nil 이 할당된다.

멤버 와이즈 이니셜라이저

  • 클래스 는 멤버와이즈 이니셜라이저를 갖지 않고, 사용자가 직접 정의한 이니셜라이저가 있지 않는 이상 기본 이니셜라이저 init()
    존재한다.
  • 따라서 만약 사용자가 이니셜라이저를 하나라도 정의했다면 기본 이니셜라이저는 사용할 수 없다. 이는 구조체 에서도 마찬가지이다.
  • 구조체 의 경우 모든 프로퍼티가 있는 이니셜 라이저와 일부 프로퍼티만 매개변수로 갖는 이니셜라이저가 존재하기때문에 따로 이니셜라이저를 정의할 필요가 없다. 이를 멤버와이즈 이니셜라이저 라고 한다.

초기화 위임

  • 값 타입인 구조체와 열거형에서는 이니셜라이저 내부에서 이니셜라이저를 호출할 수 있다.
  • self.init(~~) 을 통해 호출하면 된다.
  • 하지만 초기화 위임을 통해 이니셜라이저를 정의했다는 것은, 이미 사용자가 이니셜라이저를 정의하고 있다는 뜻이며, 이는 기본 이니셜라이저를 사용할 수 없다는 뜻이다. 따라서 초기화 위임을 구현하고자 한다면 최소 2개 이상의 사용자 정의 이니셜라이저 가 필요하다.

실패 가능한 이니셜라이저

  • 이니셜라이저 매개변수로 전달되는 초기값이 잘못된 경우, 인스턴스 생성에 실패하도록 하는 역할
  • 인스턴스 생성에 실패하면 nil을 반환한다.
  • 그래서 실패가능한 이니셜라이저의 반환타입은 옵셔널 타입이다.
class PersonD{
	var name: String
    var age: Int
    var nickName: String?
    
    init?(name: String, age: Int, nickName: String){
    	if (0...123).contains(age) == false{
        	return nil
        }
        if name.characters.count == 0{
        	return nil
        }
        
        self.name = name
        self.age = age
    }
}

let john: PersonD = PersonD(name: "john", age: 10, nickName: "J") // 오류발생 init? 이니셜라이저에 의해 PersonD? 타입을 반환하는데 PersonD로 받고 있다!

let john: PersonD? = PersonD(name: "john", age: 23, nickName: "J")

let joker: PersonD? = PersonD(name: "joker", age: 123)
let batman: PersonD? = PersonD(name: "", age: 12)

print(joker) // nil
print(batman) // nil

디이니셜라이저

  • deinit 은 클래스의 인스턴스가 메모리에서 해제되기 직전에 호출된다.
  • 인스턴스가 해제되는 시점에 해야할 일을 구현할 수 있다.
class PersonE{
	var name: String
    var pet: Puppy?
    var child: PersonC
    
    init(name: String, child: PersonC){
    	self.name = name
        sel.child = child
    }
    
    deinit{ 
    	if let petName = pet?.name{
        	print("\(name)\(child.name)에게 \(petName)을 양도합니다.")
            self.pet?.owner = child
        }
    }
}

var donald: PersonE? = PersonE(name: "donald", child: "jenny")
donald?.pet = happy
donald = nil // donald 인스턴스가 필요없기떄문에 메모리에서 해제된다.
// donal가 jenny에게 happy를 양도합니다.
profile
개발자 지망생

0개의 댓글