seong_hye, the developer

Swift) 문법 정리 - 생성자 본문

IOS/UIKit

Swift) 문법 정리 - 생성자

seong_hye 2022. 8. 2.

 

객체를 만들기 위해 가장 먼저 필요로 하는 것이 있다.

가진 속성을 초기화를 필요로 하기에 생성자를 가장 먼저 필요로 하게된다.

 그렇다면 생성자란 무엇일까?

생성자는 클래스, 구조체, 열거형에서 인스턴스를 준비하기 위한 과정으로 

인스턴스의 프로퍼티들마다 초기값을 설정해주고

새 인스턴스를 사용하기 전에 필요한 설정과 초기화를 수행하는 과정을 말한다. 

각각의 타입에서 새로운 인스턴스를 만들 수 있는 특수한 메서드와 같은 역할을 하는 생성자를 정의하여 사용할 수 있다.

생성자의 가장 중요한 역할은 새로운 인스턴스가 처음 사용되기 전에 올바르게 초기화되는 것을 보장하는 것이다.


모든 생성자가 동일하지는 않다.

특히, 구조체와 클래스의 생성자에는 차이가 있다.

표를 통해 간단히 정리하고 내용을 정리해볼까 한다.

구분 구조체(Struct) 클래스(Class)
지정 생성자 init(파라미터) {} init(파라미터) {}
편의 생성자 - convenience init(파라미터){}
필수 생성자 - required init(파라미터){}
실패가능 생성자 init?(파라미터){}
init!(파라미터){}
init?(파라미터){}
init!(파라미터){}
소멸자 - deinit()

 


지정 생성자

init(...)형태를 가지는 일반적인 생성자

모든 저장 속성을 초기화 해야함

저장속성의 선언과 동시에 값을 저장하거나 저장 속성을 옵셔널 타입으로 선언하는 것도 가능

오버로딩이 가능하므로, 다양한 파라미터 조합으로 지정 생성자 구현 가능

따로 지정하지 않아도 모든 저장 속성이 초기화되는 경우, 기본 생성자 제공 => init()

생성자를 1개이상 구현하면 기본 생성자를 제공하지 않음

class Animal {
	var name: String
    var weight: Double
    
    init(name: String, weight: Double) {
    	self.name = name
        self.weight = weight
    }
}

편의생성자

클래스만 가지는 생성자로

지정생성자보다 적은 갯수의 파라미터로 보다 편리하게 생성하기 위한 서브 개념의 생성자

지정 생성자에 의존 및 호출

클래스에서 초기화 과정을 간편하게 제공하기 위함

편의 생성자는 다른 편의 생성자를 호출하거나 지정생성자를 호출해야함( 궁극적으로 지정생성자 호출)

실질적으로 가능한 지정생성자의 갯수를 줄이고, 편의 생성자에서 지정 생성자 호출하도록 하는 것이 바람직함

상속했을 때, 편의 생성자의 경우 서브 클래스에서 재정의를 못함

class Animal {
	var name: String
    var weight: Double
    
    init(name:String, weight: Double) {
    	self.name = name
        self.weight = weight
    }
    
    convenience init(name: String) {
    	self.init(name: name, weight: 10.0)
    }
}

 

상속관계에서 생성자 위임 규칙

출처: 애플 공식문서

 

델리게이트 업

하위 클래스의 지정생성자는 슈퍼클래스의 지정생성자를 반드시 호출해야함

(하위 클래스의 저장 속성을 초기화하고 상위 클래스의 저장속성을 초기화해야함)

 

델리게이트 어크로스

편의 생성자는 동일한 클래스에서 다른 편의 생성자 또는 지정 생성자를 호출해야하고

궁극적으로는 지정생성자를 호출해야 함

(궁극적으로 지정생성자만이 해당 단계의 모든 저장값을 초기화 함)

 

class Aclass {
	var x: Int
    var y: Int
    
    init(x: Int, y: Int) {
    	self.x = x
        self.y = y
    }
}

class Bclass: Aclass {
	var z: Int
    
    init(x: Int, y:Int, z: Int) {
    	self.z = z		// 하위 클래스 메모리 먼저 초기화
        super.init(x:x, y:y)	// 상위 클래스 지정 생성자 호출
	}
 }

필수 생성자

클래스의 생성자 앞에 required 키워드를 붙이면 하위 클래스에서

반드시 파라미터 이름과 타입이 동일한 생성자를 구현해야 함

하위 클래스에서 필수 생성자 구현시, override 키워드 없이 required 키워드만 붙이면 됨

필수 생성자 자동 상속 조건 : 다른 지정 생성자를 구현 안하면 자동으로 필수 생성자 상속됨

class Aclass {
	var x: Int
    required init(x: Int) {
    	self.x =x
    }	
}

class Bclass: Aclass {
//	required init(x: Int) {		===> 다른 지정 생성자 구현 안하면 자동 상속
//  	self.x =x
//  }
}

class Cclass: Aclass {
	init() {
    	super.init(x:0)
    }
    
    required init(x: Int) {
    	self.x = x
    }
}

 

왜 알아야 하는가?

애플이 만들어 놓은 프레임워크에는 많이 사용되고 있기에 알고 있어야 함

예로 UIView, UIController를 상속하여, 지정생성자를 구현하면

아래의 필수 생성자를 반드시 구현해야함

required init?(coder: NSCoder) {
	fatalError("init(coder:( has not been implemented")
}

실패 가능 생성자

인스턴스 생성시, 실패 가능성을 가진 생성자 -> 실패 시 nil 리턴

생성자에 ?를  붙여 init?(...)으로 정의

(다만, 오버로딩으로 인한 구분이 안되므로 해당이름을 가진 생성자는 유일한 생성자여야 함)

 

왜 만들었을까?

실패가 불가능하게 만들어서, 아예 에러가 나고 앱이 완전히 꺼지는 가능성 보다는
실패 가능 가능성 생성자를 정의하고 그에 맞는 예외 처리를 하는 것이 더 올바른 방법이기 때문

struct Animal {
	let species: String
    
    init?(species: String) {
    	if species.isEmpty {
        	return nil
		}
        self.species = species
    }
}

 

유의해야할 점

실패불가능 생성자는 다른 실패 가능 생성자를 호출 불가능

상위 - init?(실패가능)  => 하위 - init(실패불가능) (o)

 상위 - init(실패불가능) => 하위 - init?(실패가능) (x)

 

두 경우 모두 초기화 실패를 유발하는 다른 생성자에 위임하면

전체 초기화 프로세스가 즉시 실패하고 더 이상 초기화 코드가 실행되지 않음


소멸자

인스턴스 해제시, 정리가 필요한 내용을 정의

클래스에는 최대 1개의 소멸자가 존재

인스턴스가 메모리에서 제거되기 직전에 자동으로 호출되는 메서드 부분

class Animal {
	deinit{
    	print("객체의 소멸")
    }
}

참고자료)

https://zrr.kr/qNHN

 

앨런 Swift문법 마스터 스쿨 (온라인 BootCamp - 2개월과정) 강의 - 인프런

Swift문법을 제대로 이해, 활용해보고자 하는 철학을 바탕으로 과정이 설계되었습니다. 코딩에 대해 1도 모르는 비전공자를 시작으로 네카라쿠배에 입사할 수 있는 초고급 수준까지 올리는 것을

www.inflearn.com

'IOS > UIKit' 카테고리의 다른 글

Cocoapods  (0) 2022.08.02
Alamofire  (0) 2022.08.02
Url Session  (0) 2022.08.02
UIView Animation  (0) 2022.08.02
DispatchSourceTimer  (0) 2022.08.02
Comments