소문자로 시작하는 self는 "모든 인스턴스들이 암시적으로 생성하는 프로퍼티"입니다.
특정 코드 내부 및 외부에서 모두 사용할 수 있으며, 자기 자신(인스턴스)을 가리키는 목적으로 주로 사용됩니다.
✅ 인스턴스를 가르키는 self
- 인스턴스의 프로퍼티를 명확히 가리키기 위해 사용합니다.
class Man{ var name: String init(name: String){ self.name = name //인스턴스의 프로퍼티를 보다 명확하게 가리킴 } }
- 값 타입(구조체, 열거형)에서 인스턴스를 변경할 때 사용합니다.
struct Game{ mutating func restart(){ self = Game() //값 타입(구조체, 열거형)에서 인스턴스의 데이터를 변경할 수도 있음 } }
- 타입 속성/메서드에서 사용할 때 인스턴스가 아닌 해당 타입을 가리킵니다.
class ABC{ static var abc = "클래스 이름은 ABC" static func play() -> String{ return self.abc // 인스턴스가 아닌 타입을 가리킴 } }
- 타입 인스턴스를 가리킬 때는 타입 뒤에 self를 작성합니다.
class ABC{ static var abc = "클래스 이름은 ABC" } var kim: ABC.Type = ABC.self // 타입 인스턴스를 가리키는 경우 사용 // ABC.Type == 메타타입 ABC.abc // 클래스 이름은 ABC (ABC.abc -> 단축 표현) ABC.self.abc // 클래스 이름은 ABC (ABC.self.abc -> 정식 표현) Int.max // 9223372036854775807 Int.self.max // 9223372036854775807 \
대문자로 시작하는 Self는 특정 타입의 코드 안에서 사용되며, "해당 코드의 타입"을 가리킵니다.
✅ 해당 타입을 가르키는 Self
- 타입을 선언하는 위치에서 Self를 작성합니다.
class Man{ var name: String var age: Int var myType: Self{ // Self = Man 타입 -> 특정 타입 내부에서 해당 타입을 가리킴 return Man(name: "아무개", age: 0) as! Self } init(name: String, age: Int){ self.name = name self.age = age } } var kim = Man(name: "철수", age: 25) print(type(of: kim)) print(type(of: kim.myType)) print(kim.myType)
- 프로토콜에서의 Self는 채택할 타입을 가리킵니다.
protocol A{ func a() -> Self } class Man: A{ func a() -> Self{ // 프로토콜이 채택한 타입을 가리킴 return self } } var kim = Man() kim.a() //Man 타입