
오늘은 인스턴스에 대해 정리해보려고 한다.
인스턴스란 클래스나 구조체 등에 소속된 개별적인 객체를 말한다.
객체 지향 언어에서 객체가 메모리에 할당되어 실제로 사용될 때 인스턴스라고 말한다.
객체와 인스턴스의 차이점은 객체는 '선언'하는 것이고, 인스턴스는 객체를 '실체화'하는 것이라고 생각하면 될 것 같다.
우리가 인스턴스를 사용하기 위해서는 초기화를 진행해야 한다. 초기화는 새로운 인스턴스를 사용할 준비를 하기 위해 저장 프로퍼티의 초깃값을 설정하는 등의 일을 진행하는 것으로, 초기화를 해줘야 인스턴스를 사용할 수 있다.
초기화를 해주는 방법 중 하나로 이니셜라이저를 정의하여 초기화를 직접 구현할 수 있는데, 이니셜라이저를 정의하면 새로운 인스턴스를 생성할 수 있는 메소드가 된다.
이니셜라이저는 반환 값이 없고, 그저 인스턴스의 사용을 위해 초기화하는 용도이다.
이니셜라이저 (init)
초깃값(initial value)과 기본값(default value)
struct Area {
	var squareMeter: Double
	init() {    //init으로 인스턴스 초기화
		squareMeter = 0.0    //프로퍼티에 초기값 할당
	}
}
let room: Area = Area()
print(room.squareMeter)    //0.0
struct Area {
	var squareMeter: Double = 0.0    //프로퍼티 기본값 할당
}
let room: Area = Area()
print(room.squareMeter)    //0.0사용자 정의 이니셜라이저 (이니셜라이저 매개변수)
//사용자 정의 이니셜라이저
struct Area {
    var squareMeter:Double
    
    init(fromPy py: Double) {    //첫 번째 이니셜라이저
        squareMeter = py * 3.3058
    }
    
    init(fromSquareMeter squareMeter: Double) {     //두 번째 이니셜라이저
        self.squareMeter = squareMeter
    }
    
    init(value: Double) {   //세 번째 이니셜라이저
        squareMeter = value
    }
    
    init(_ value: Double) { //네 번째 이니셜라이저
        squareMeter = value
    }
}
let roomOne: Area = Area(fromPy: 15.0)
print(roomOne.squareMeter    //49.857
let roomTwo: Area = Area(froomSquareMeter: 33.06)
print(roomTwo.squareMeter)    //33.06
let roomThree: Area = Area(value: 30)    //30
let roomFour: Area = Area(10)    //10
Area()  //에러 : 사용자 정의 이니셜라이저를 사용했는데, 기본 이니셜라이저를 정의하지 않았기 때문옵셔널 프로퍼티 타입
class Person {
    var name: String
    var age: Int?   //옵셔널로 프로퍼티 할당
    
    init(name: String) {
        self.name = name
    }
}
let ted: Person = Person(name: "Ted")   //Ted
print(ted.age)  //nil
ted.age = 99
print(ted.age)  //Optional(99)상수 프로퍼티
class Person {
    let name: String    //상수 프로퍼티 (let)
    var age: Int?   //옵셔널로 프로퍼티 할당
    
    init(name: String) {
        self.name = name
    }
}
let ted: Person = Person(name: "Ted")   //Ted
ted.name = "rlaxogud"   //에러기본 이니셜라이저와 멤버와이즈 이니셜라이저
저장 프로퍼티를 선언할 때 기본값을 지정해주지 않으면 이니셜라이저에서 초깃값을 설정해야함
--> 하지만 프로퍼티 때문에 매번 이니셜라이저를 추가하고 변경하는 것은 귀찮은 일임!
구조체에서는 이니셜라이저를 구현하지 않으면 프로퍼티의 이름을 매개변수로 갖는 이니셜라이저인 '멤버와이즈 이니셜라이저'를 제공함 (클래스는 제공하지 않음)
--> 이로 인해 구조체에서는 이니셜라이저를 굳이 선언해주지 않아도 됨!!
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 = Point(x: 0,y: 0)  //Point를 class로 바꾸면 이렇게 사용하지 못함 (init이 없기 때문에 -> class는 멤버와이즈 이니셜라이저를 제공하지 않기 때문에)
let size: Size = Size(width: 50, height: 50)
let somePoint: Point = Point()
print(somePoint)
let someSize: Size = Size(width: 50)    //필요한 매개변수만 초기화 할 수도 있음
let anotherPoint: Point = Point(y: 40)사용자 정의 이니셜라이저 : 사용자가 이니셜라이저에 프로퍼티(변수, 상수 등)를 정의해놓은 것
사용자 정의 이니셜라이저를 정의해주지 않으면 모든 프로퍼티에 기본값이 지정되어 있다는 전제하에 기본 이니셜라이저를 사용함
기본 이니셜라이저 : 프로퍼티 기본값으로 프로퍼티를 초기화해서 인스턴스를 생성
초기화 위임
enum Student {
    case elementary, middle, high
    case none
    
    init() {    //사용자 정의 이니셜라이저가 있어서, init()을 구현해줘야 기본 이니셜라이저를 사용할 수 있음
        self = .none
    }
    
    init(koreanAge: Int) {  //사용자 정의 이니셜라이저
        switch koreanAge {
        case 8...13:
            self = .elementary
        case 14...16:
            self = .middle
        case 17...19:
            self = .high
        default:
            self = .none
        }
    }
    
    init(bornAt: Int, currentYear: Int) {   //사용자 정의 이니셜라이저
        self.init(koreanAge: currentYear - bornAt + 1)
    }
}
var younger: Student = Student(koreanAge: 16)   //middle
younger = Student(bornAt: 1998, currentYear: 2016)  //high실패 가능한 이니셜라이저
class Person {
    let name: String
    var age: Int?
    
    init?(name: String) {   //실패 가능한 이니셜라이저
        if name.isEmpty {
            return nil
        }
        self.name = name
    }
}
let ted: Person? = Person(name: "Ted")디이니셜라이저 (인스턴스의 소멸)
class FileManager {
    var fileName: String
    
    init(fileName: String) {
        self.fileName = fileName
    }
    func openFile() {
        print("Open File: \(self.fileName)")
    }
    func writeFile() {
        print("Write File: \(self.fileName)")
    }
    func closeFile() {
        print("Close File: \(self.fileName)")
    }
    deinit {
        print("Deinit instance")
        self.writeFile()
        self.closeFile()
    }
}
var fileManager: FileManager? = FileManager(fileName: "abc.txt")
if let manager: FileManager = fileManager {
    manager.openFile()  //Open File: abc.txt
}
fileManager = nil   //Deinit instance
                    //Write File: abc.txt
                    //Close File: abc.txt[출처] 스위프트 프로그래밍 (야곰), 야곰의 스위프트 기초문법 강좌, 개발하는 정대리 스위프트 강좌