class 클래스명 {
// 클래스 변수,함수 및 이니셜라이저
}
class Car {
var model: String
var year: Int
// 커스텀 이니셜라이저
init(model: String, year: Int) {
self.model = model
self.year = year
}
// 디이니셜라이저
// 인스턴스가 메모리에서 해제될 때 실행
deinit {
print("\(model)이 메모리에서 해제되었습니다.")
}
}
// 커스텀이니셜라이저 설정안하면 매개변수에 값 못넣음
// Car? 형식으로 닐러블하게 데이터타입 작성하면
// JS 어썰션, as Any 등으로 해결가능
var car: Car = Car(model: "Tesla model S", year: 2022);
print(car) // => (model: "Tesla Model S", year: 2022)
class 슈퍼클래스 {
// 슈퍼클래스 속성, 메서드 정의
}
// 상속
class 서브클래스: 슈퍼클래스 {
// 서브클래스 추가 속성 메서드 정의
}
// exam
class Vehicle {
var currentSpeed: Double = 0.0
func description() -> String {
return "now speed is \(currentSpeed)"
}
}
class Bicycle: Vehicle {
var hasBasket: Boolean = false
}
let bicycle = Bicycle()
bicycle.currentSpeed = 30.0
bicycle.description(); // now speed is 30.0
class Vehicle {
var currentSpeed: Double = 0.0
func description() -> String {
return "now speed is \(currentSpeed)"
}
}
class Car: Vehicle {
var gear: Int = 1
// 속성 및 함수 재정의 시 override 키워드 사용
override func description() -> String {
return "car in gear \(gear) and speed \(currentSpeed)"
}
}
let car = Car()
car.currentSpeed = 60.0
car.gear = 3
car.discription() // car in gear 3 and speed 60.0
서브클래스에서 슈퍼클래스를 참조할때 사용하는 키워드다
class Bus: Vehicle {
var passengerCount = 0
override func description() -> String {
return super.description + " with \(passengerCount) passengers"
}
}
let bus = Bus()
bus.passengerCount = 30
bus.description() // now speed 0.0 with 30 passengers
Swift는 메모리 관리가 ARC(Automatic Reference Counting) 에 의해 이루어지는데 ARC는 객체의 참조 횟수를 추적해서 아무도 객체를 참조하지 않게 되면 메모리에서 자동 해제되는 식으로 관리가 이루어진다.
이전 글에서 다뤘듯 구조체와 클래스의 차이점 중 하나가
클래스 = 참조형 이라고 설명했었는데 이에 따라 클래스는 ARC의 관리대상이 된다.
class Person {
let name: String
init(name: String) {
self.name = name
print("\(name) 생성")
}
deinit {
print("\(name) 메모리 해제")
}
}
var alice = Person(name: Alice) // 클래스 참조 1
var bob = alice // 클래스 참조 2
alice = nil // alice 참조 해제 => 클래스 참조 1
bob = nil // 참조 0 => 메모리 해제
이런식으로 메모리 참조가 0이 되면 메모리에서 해제 되는 식이다.
그런데 참조가 엮여있는 강한 참조, 순환 참조가 있을 경우에는 위와같은 식으로 메모리에서 해제가 되지 않는데
강한 참조는 보통 의도에 의해 메모리에서 해제되지 않지만 순환 참조의 경우는 이를 방지하기 위한 두가지 방법이 있다.
그게 바로 약한 참조(weak), 미소유 참조(unowned) 이다.
class Person {
var pet: Pet?
deinit {
print("Person 메모리 해제")
}
}
class Pet {
var person: Person?
deinit {
print("Pet 메모리 해제")
}
}
var person = Person()
var pet = Pet()
person?.pet = pet
pet?.person = person
person = nil
pet = nil
// 일반적인 상황에서는 메모리가 해제됐겠지만 순환참조로 인해
// deinit 호출이 안된다.
Person 과 Pet이 서로 strong으로 참조하니 메모리에서 해제되지 않는다.
class Person {
// weak 키워드 추가
weak var pet: Pet?
deinit {
print("Person 메모리 해제")
}
}
class Pet {
var person: Person?
deinit {
print("Pet 메모리 해제")
}
}
var person = Person()
var pet = Pet()
person?.pet = pet
pet?.person = person
person = nil // Person 해제
pet = nil // Pet 해제
class CreditCard {
unowned var owner: Person
init(owner: Person) {
self.owner = owner
}
deinit {
print("CreditCard 해제")
}
}
class Person {
var card: Card?
deinit {
print("Person 해제")
}
}
var person = Person()
person.card = CreditCard(owner: person!)
p = nil
// Person 해제
// CreditCard 해제
unowned는 nil이 될 수 없다는 전제하에 사용
owner가 먼저 해제되고 unowned 참조에 접근하면 crash 발생