갓생 살기 2회차 .. 오늘도 화이팅 !
struct
구조체의 생성자를 알아보자 !
struct Color {
let red, green, blue: Double
init() { // 기본 생성자. 기본값을 설정하면 자동으로 제공됨
red = 0.0
green = 0.0
blue = 0.0
}
init(white: Double) {
red = white
green = white
blue = white
}
init(red: Double, green: Double, blue: Double) {
self.red = red
self.green = green
self.blue = blue
}
}
struct Color1 {
let red, green, blue: Double
init() { // 구조체는 다른 생성자를 호출하는 방식도 가능
self.init(red: 0.0, green: 0.0, blue: 0.0)
}
init(white: Double) { // 구조체는 다른 생성자를 호출하는 방식도 가능
self.init(red: white, green: white, blue: white)
}
init(red: Double, green: Double, blue: Double) {
self.red = red
self.green = green
self.blue = blue
}
}
질문!
struct Color
와 struct Color1
의 차이점을 한 번 슥 훑어보죠.
일단 struct Color
는 기본 생성자를 사용하여 구현을 했습니다. 킹치만 .. struct
에선 이런 방식이 올바른 구현은 아니에요 ..
코드가 중복되지 않고, 유지보수를 더 잘 할 수 있도록 ! 우리는 struct Color1
처럼 !
init()
으로 생성자를 만들고 만들어진 생성자를 호출하는 방식을 사용할겁니다..!
구조체의 경우 자체 지정생성자를 작성하면, 생성자 내에서 self.init()
을 사용하여 다른 이니셜라이저를 오출하도록 할 수 있어요.
그렇담! class
의 상속과 지정, 편의 생성자 사용 예시를 봐봐요.
먼저 지정생성자!
class Aclass {
var x: Int
var y: Int
init(x: Int, y: Int) { // 지정생성자 - 모든 저장 속성 설정
self.x = x
self.y = y
}
}
평소에 우리가 알던 init()
을 사용하여 초기값을 설정해줬네요?
다음은 편의생성자!
class Aclass {
var x: Int
var y: Int
init(x: Int, y: Int) { // 지정생성자 - 모든 저장 속성 설정
self.x = x
self.y = y
}
convenience init() { // 편의생성자 - (조금 편리하게 생성) 모든 저장 속성을 설정하지 않음
self.init(x: 0, y: 0)
}
}
편의생성자는 편리하게 생성하기 위한 생성자라고 생각하면 될 듯?
왜냐면 편의생성자는 모든 속성을 초기화 할 필요가 없응께..
근데 여기서 Aclass를 상속 받는 Bclass 가 있다면 ?!
class Bclass: Aclass {
var z: Int
init(x: Int, y: Int, z: Int) {
self.z = z // 먼저 자신부터 초기화하고,
super.init(x: x, y: y) // 상위의 지정생성자를 호출 !
}
convenience init(z: Int) {
self.init(x: 0, y: 0, z: z)
}
convenience init() {
self.init(z: 0)
}
func doSomething() {
print("Do something")
}
}
다음은 애플 공식 문서의 예제를 한 번 살펴볼까요?
class Vehicle {
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheel(s)"
}
}
let vehicle = Vehicle()
print("Vehicle: \(vehicle.description)") // Vehicle: 0 wheel(s)
저장속성 numberOfWheels
에 0
이라는 기본값을 제공했기 때문에, 기본 생성자 init()
이 자동으로 제공됩니다!
이제 서브클래스로 넘어가겠음 👍🏻
class Bicycle: Vehicle {
override init() {
super.init() // 수퍼클래스 호출 반드시 필요
numberOfWheels = 2 // 초기화의 2단계 값설정
}
}
// 커스텀 init() 정의 ===> 생성자가 상위클래스의 이름과 동일 하므로 재정의 키워드 필요
// 상위 지정생성자 호출하여 메모리 초기화 후, 상위에서 구현한 속성에 접근하여 2로 셋팅(2단계 값설정)
let bicycle = Bicycle()
print("Bicycle: \(bicycle.description)") // Bicycle: 2 wheel(s)
대충 .. 주석으로 적어놓았습니다잉?
다음 서브클래스!
class Hoverboard: Vehicle {
var color: String
// (읽기) 계산 속성 재정의
override var description: String {
return "\(super.description) in a beautiful \(color)"
}
init(color: String) {
self.color = color // (현재 클래스) 저장 속성 초기화
super.init() // =====> 여기서 암시적으로 호출됨
}
}
let hoverboard = Hoverboard(color: "silver")
print("Hoverboard: \(hoverboard.description)") // Hoverboard: 0 wheel(s) in a beautiful silver
또, color
라는 저장속성이 생겼으니 color
저장속성을 초기화하고, super.init()
을 하는 모습 .. 좋네요 !
필수 생성자를 사용하는 예시를 보여드릴게요!
어라? 분명 UIView
를 상속 받았는데?
init
이 안필요하나?
require
은 이때 등장합니다! 애플이 미리 만들어놓은 Framework 에서 활용이 되죠 ..
사실 위의 코드는
class AView: UIView {
required init?(coder: NSCoder) { // 구현을 안해도 자동상속
fatalError("init(coder:) has not been implemented")
}
}
의 코드가 숨겨져 있었단 사실 ..! ㅎㄷㄷ;;;
TIL 시리즈는 막연히 제가 배운 걸 기록하는 공간입니다.