self vs Self
self 키워드의 사용 (소문자)
- Swift에서
self는 인스턴스를 참조하거나, 타입 내부의 특정 상황에서 타입 자체를 지칭할 때 사용된다
인스턴스를 가리키기 위해 사용
- 클래스 또는 구조체의 인스턴스를 초기화하거나 프로퍼티에 접근할 때
self를 사용하여 인스턴스 자신을 참조한다
class Person {
var name: String
init(name: String) {
self.name = name
}
}
값 타입(구조체, 열거형)에서 인스턴스 값 자체를 치환하기 위해 사용
- 구조체 또는 열거형에서
self를 사용하여 기존 인스턴스를 새로운 인스턴스로 완전히 교체할 수 있다
- 이는 값 타입에서만 가능한 방식이다
struct Calculator {
var number: Int = 0
mutating func plusNumber(_ num: Int) {
number += num
}
mutating func reset() {
self = Calculator()
}
}
타입 멤버에서 사용하면, 인스턴스가 아닌 타입 자체를 가리킴
- 클래스, 구조체 또는 열거형의 타입 속성이나 타입 메서드를 정의할 때
self는 해당 타입 자체를 의미한다
struct MyStruct {
static let club = "iOS부서"
static func doPrinting() {
print("소속은 \(self.club)입니다.")
}
}
타입 인스턴스와 메타타입
타입 인스턴스
- 타입 인스턴스란, 특정 타입을 직접 나타내는 것을 의미한다 (예:
SomeClass.self)
- 타입 인스턴스를 사용하면 타입 자체를 참조할 수 있으며, 이때
self를 사용하여 타입 인스턴스를 가리킬 수 있다
class SomeClass {
static let name = "SomeClass"
}
let classTypeInstance: SomeClass.Type = SomeClass.self
- 메타타입은 타입 자체를 나타내는 특별한 타입이다
- 즉, 클래스, 구조체, 열거형 등의 타입 정보를 나타낸다
- 메타타입은 타입의 인스턴스를 가리키는 것이 아니라, 타입 자체를 가리킨다
Type 접미사를 사용하여 메타타입을 표현한다
class Animal {
static let species = "Mammal"
}
let animalType: Animal.Type = Animal.self
print(Animal.species)
print(Animal.self.species)
- 여기서
Animal.Type 는 Animal 타입의 메타타입을 의미한다
- 즉,
animalType 은 Animal 타입 자체를 나타내는 객체이다
- 다음과 같이 메타타입으로도 타입의 속성에 접근할 수 있다
Self 키워드의 사용 (대문자)
- Swift에서
Self는 해당 타입 자체를 의미하며, 특정 타입 내부에서 사용된다
타입 선언 위치에서 사용
- 특정 타입의 선언 위치에서
Self는 타입 이름 대신 사용될 수 있다
extension Int {
static let zero: Self = 0
var zero: Self {
return Self.zero
}
}
동일한 예제를 타입 이름을 사용하여 작성한다면?
extension Int {
var zero: Int {
return Int.zero
}
}
타입 속성/메서드에서 사용
- 타입 내부의 타입 속성 또는 타입 메서드에서
Self를 사용하여 타입 자체를 가리킨다
extension Int {
static func toZero() -> Self {
return Self.zero
}
}
인스턴스 메서드에서 사용
- 인스턴스 메서드에서
self는 인스턴스 자체를 의미하며, Self는 타입을 의미한다
extension Int {
func toZero() -> Self {
return Self.zero
}
}
프로토콜에서의 Self 사용
- Swift에서
Self는 프로토콜 내에서 해당 타입을 가리킬 때 사용된다
- 프로토콜 메서드가
Self를 반환 타입으로 가지는 경우, 구현하는 타입이 해당 메서드를 구현할 때 반드시 같은 타입을 반환해야 한다
protocol Clonable {
func clone() -> Self
}
struct User: Clonable {
var name: String
func clone() -> Self {
return User(name: self.name)
}
}
BinaryInteger 프로토콜 사용 예시
- Swift의
BinaryInteger 프로토콜을 채택하는 타입 (Int, UInt 등)에서도 Self를 사용할 수 있다
- 프로토콜의 기본 구현 메서드에서
Self를 사용하여 타입이 정확히 지정되지 않아도 제네릭하게 동작하도록 할 수 있다
extension BinaryInteger {
func squared() -> Self {
return self * self
}
}
let intValue: Int = 8
print(intValue.squared())
let uintValue: UInt = 12
print(uintValue.squared())
요약
self: 인스턴스를 가리키거나, 타입 내부의 특정 상황에서 타입 자체를 지칭할 때 사용된다
Self: 특정 타입 내부에서 타입 자체를 가리키거나, 프로토콜에서 해당 타입을 의미할 때 사용된다
- 타입 인스턴스: 특정 타입 자체를 참조하기 위한 인스턴스로,
self를 사용하여 참조할 수 있다
- 메타타입: 타입 자체를 가리키는 특별한 타입으로,
Type 접미사를 사용하여 표현한다
- 프로토콜에서
Self를 사용하면, 제네릭하게 타입을 정의하고, 확장할 수 있다