class SomeClass{
init(){
}
}
struct SomeStruct{
init(){
}
}
enum SomeEnum{
case someCase
init(){
self = .selfCase
}
}
//클래스나 구조체는 init 이 비워있어도 되지만, 열거형은 초기화할 때 반드시 case 중 하나가 되어야 함
struct Area{
var squareMeter: Double
init(){
squareMeter = 0.0 //Default Value 를 미리 작성하는 것
}
}
let room: Area = Area()
print(room.squareMeter) //0.0
**초기화 후에 값이 확정되지 않은 저장 프로퍼티는 존재할 수 없음
→ 위와 같이 init( ) 함수 안에서 기본값을 할당할 수 있긴 하지만, 프로퍼티에 바로 기본값을 할당하는 법도 있음
struct Area{
var squareMeter: Double = 0.0
}
let room: Area = Area()
print(room.squareMether) //0.0
struct Area{
var squareMeter: Double
init(fromPy py: Double){
squareMeter = py * 3.3
}
init(fromSquareMeter squareMeter: Double){
self.squareMeter = squareMeter
}
init(value: Double){
squareMeter = value
}
init(_ value: Double){
squareMeter = value
}
}
let roomOne: Area = Area(fromPy: 15.0)
let roomTwo: Area = Area(fromSquareMeter: 33.06)
→ 위와 같이 여러 개의 initializer 를 사용할 수 있음.
class Person{
var name: String
var age: Int?
init(name: String){
self.name = name
}
}
**상수 프로퍼티는 본인 클래스에서만 초기화 가능 → 상속 받은 자식 클래스는 상수 프로퍼티 초기화 불가
class Person{
let name: String
var age: Int?
init(name: String){
self.name = name
}
}
let yagom: Person = Person(name: "yagom")
yagom.name = "Eric" //오류 발생!
Default Initializer:
Memberwise Initializer:
struct Point{
var x: Double = 0.0
var y: Double = 0.0
}
struct Size{
var width: Double = 0.0
var height: Double = 0.0
}
let point: Point = (x: 0, y: 0)
let size: Size = Size(width: 50.0, height: 50.0)
//위와 같이 매개변수로 프로퍼티의 이름과 할당할 값을 모두 포함하여 전달함.
let somePoint: Point = Point()
let someSize: Size = Size(width:50)
//width 에만 값을 할당하고 싶으면 그렇게 해도 됨
//그럼 자동으로 height 는 0.0 으로 초기화됨
let anotherPoint: Point = Point(y:100)
//위도 마찬가지
**Memberwise Initializer 는 구조체에서만 가능! 클래스는 X
Initializer 는 인스턴스 초기화의 일부를 수행하기 위해 다른 이니셜라이저를 호출할 수 있다
→ 그러려면 2개의 사용자 정의 init ( ) 함수가 있어야 함
값 유형 (구조체, 열거형)에서만 사용 가능
클래스의 초기화 위임은 상속임
Why use? → 코드의 중복 예방
struct Frame {
var x: Int
var y: Int
init(x: Int, y: Int) {
self.x = x
self.y = y
}
init(y: Int) {
self.init(x: 0, y: y) // 다른 이니셜라이저를 호출
}
}
let rect = Frame(x: 10, y: 10)
let originRect = Frame(y: 5)
struct Animal {
let species: String
init?(species: String) {
if species.isEmpty { return nil } // nil 반환 시 return 사용
self.species = species
}
}
//init?을 옵셔널로 설정하였기에 nil 반환이 가능₩
//Animal? 도 옵셔널로 정의
if let animal: Animal? = Animal(species: "Dog"){
print(animal.species)
}
else{
print("error initializing")
}
//Dog
if let animal: Animal? = Animal(species: 2){
print(animal.species)
}
else{
print("error initializing")
}
//error initializing
enum Student: String{
case elementary = "초등학생", middle = "중학생", high = "고등학생"
init?(koreanAge: Int){
switch koreanAge{
case 8...13:
self = .elementary
case 14...16:
self = .middle
case 17...19:
self = .high
default:
return nil //이것도 init? () 으로 선언해서 가능한 것
}
}
init?(bornAt: Int, currentYear: Int){
self.init(koreanAge: currentYear - bornAt + 1) //초기화 위임!
}
}
var younger: Student? = Student(koreanAge: 25)
print(younger)
//nil
younger = Student(rawValue: "고등학생")
print(younger)
//high
class SomeClass{
let someProperty: Int = {
return result
}()
}
//result 는 Int 와 반드시 같은 타입이어야 함
//즉, 반환 값의 타입은 동일
→ 클로저 뒤에 소괄호 ( ) 가 붙는 이유는 클로저를 실행하기 위함. 소괄호를 붙여주지 않으면 프로퍼티의 기본값은 클로저 그 자체가 됨.
struct Student{
var name: String?
var number: Int?
}
class SchoolClass{
var students: [Student] = {
//여기서 반환값은 반드시 [Student]이어야 한다
var arr: [Student] = [Student]()
for num in 1...15{
var student: Student = Student(name: nil, number: num) //하나씩 증가
arr.append(student)
}
}()
}
let myClass: SchoolClass = SchoolClass()
print(myClass.students.count)
//15
→ Deinitializer 는 단 하나만 구현 가능
→ 매개변수가 없고, 소괄호를 적어주지도 않음
→ 자동 호출이기 때문에 별도 코드로 호출 불가능
class SomeClass{
deinit{
print("Instance will be deallocated")
}
}
var instance: SomeClass? = SomeClass()
instance = nil
→ 즉, 따로 deinit 코드를 우리가 실행해 주는 것이 아니라, instance = nil 이 실행되면 인스턴스가 소멸되는데, 소멸 직전에 deinit { } 이 실행되는 것. 여기서 파일을 저장하거나, 제대로 닫아주는 등의 추가 작업 가능