오늘은 인스턴스에 대해 정리해보려고 한다.
인스턴스란 클래스나 구조체 등에 소속된 개별적인 객체를 말한다.
객체 지향 언어에서 객체가 메모리에 할당되어 실제로 사용될 때 인스턴스라고 말한다.
객체와 인스턴스의 차이점은 객체는 '선언'하는 것이고, 인스턴스는 객체를 '실체화'하는 것이라고 생각하면 될 것 같다.
우리가 인스턴스를 사용하기 위해서는 초기화를 진행해야 한다. 초기화는 새로운 인스턴스를 사용할 준비를 하기 위해 저장 프로퍼티의 초깃값을 설정하는 등의 일을 진행하는 것으로, 초기화를 해줘야 인스턴스를 사용할 수 있다.
초기화를 해주는 방법 중 하나로 이니셜라이저를 정의하여 초기화를 직접 구현할 수 있는데, 이니셜라이저를 정의하면 새로운 인스턴스를 생성할 수 있는 메소드가 된다.
이니셜라이저는 반환 값이 없고, 그저 인스턴스의 사용을 위해 초기화하는 용도이다.
이니셜라이저 (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
[출처] 스위프트 프로그래밍 (야곰), 야곰의 스위프트 기초문법 강좌, 개발하는 정대리 스위프트 강좌