Swift

Swift | self vs Selft에 관하여

ziziDev 2024. 5. 21. 14:17
반응형

안녕하세요!

오늘은 self 와 Self에 관하여

정리하고자 합니다

 

쉬우니까

바로 습득이 가능하실거에요!

 

지금까지 소문자 self는 많이 사용했었답니다

 

특히 클래스에서 많이 사용했던걸로 기억하는데요

보통 인스턴스나 값 자체를 치환하는 경우에도 사용합니다

 

코드를 통해서 알아보고자 합니다

 

self vs Self

|

 

우선 소문자 self에 대해서 알아보고자 합니다

self

인스턴스를 가르키기 위해 사용하는 경우

 

class Person {
	var name: String
    
	init(name: String) {
		self.name = name
	}
}

 

여기서 self는

현재 객체(instance)를 가리킵니다

인스턴스 내부에서 해당 인스턴스의 속성이나 메서드에 접근이 가능합니다

 

클래스 내부에서 보통 속성과 매개변수 이름이 동일한 경우가 있답니다

이런 경우 self 키워드를 사용하여

인스턴스의 속성임을 명시적으로 나타 낼 수 있습니다

가독성을 🆙높이고 혼동을 방지하는데 도움을 준답니다

 

 

 

새로운 값으로 속성 초기화 가능한 패턴 (값타입에서)

struct Calculator {
    var number: Int = 0
    
    mutating func plusNumber(_ num: Int) {
        number = number + num
    }
    
    // 값 타입(구조체, 열거형)에서 인스턴스 값 자체를 치환 가능
    mutating func reset() {
        self = Calculator()    // 값 타입은 새로 생성해서 치환하는 것도 가능
    }
}

 

 

구조체나 열거형은 값 타입이므로 자기 자신을 다른 구조체나 열거형으로 변경할 수가 있습니다

self에 다른 구조체나 열거형을 할당하는 것이 가능합니다

 

 

굳이 계산 구조체가 아니더라도

SomeOtherStruct()로 넣어도 된다는 말씀!

 

타입멤버에서 사용하게 된다면 인스턴스가 아닌 타입 자체를 가르킴

struct MyStruct {
    static let club = "iOS부서"
    
    static func doPrinting() {
        print("소속은 \(self.club)입니다.")
    }
}

 

여기서 self.club을 통해 정적 상수인 club에 접근을 하고 있는것을 볼 수 있습니다

 

타입 인스턴스를 가르키는 경우에 사용

(외부에서 타입을 가르키는 경우)

class SomeClass {
    static let name = "SomeClass"
}


let myClass: SomeClass.Type = SomeClass.self
// SomeClass.Type ===> 메타타입


SomeClass.name
SomeClass.self.name


Int.max
Int.self.max

 

SomeClass.self에서는

SomeClass 타입의 메타타입을 나타냅니다

메타타입은 타입 자체의 타입을 의미합니다

SomeClass.self는 SomeClass 타입의 실제 타입입니다

 

 

이제 Self에 대해서 알아보고자 합니다

 

Self

해당 타입을 나타내는 용도나 프로토콜을 채택하는 타입

 

즉 타입에 대해서 나타냅니다

 

해당 타입을 가르키는 용도에서 Self의 사용

extension Int {
    // 타입 저장 속성
    static let zero: Self = 0     // Int 타입
    //static let zero: Int = 0
    
    // 인스턴스 계산속성
    var zero: Self {  // 1) 타입을 선언하는 위치에서 사용
        return 0
    }
//    var zero: Int {
//        return 0
//    }
    
    // 2) 타입 속성/메서드에서 지칭
    static func toZero() -> Self {
        return Self.zero      // Int.zero
    }

    
    // 인스턴스 메서드
    func toZero() -> Self {
        return self.zero     // 5.zero
    }
}



Int.zero
5.zero

Int.toZero()
5.toZero()

 

타입을 선언하는 위치에서 사용하거나

타입 속성/타입메서드를 지칭하는 자리에서 대신 사용이 가능합니다

 

프로토콜에서 Self사용

프로토콜을 채택하는 해당 타입을 가르킴

 

// 이진법으로 표현된 정수에서 쓰이는 프로토콜

extension BinaryInteger {
    func squared() -> Self {  // 타입자체(Int)를 가르킴
        return self * self    // 인스턴스(7)를 가르킴
    }
}

// 간단하게 얘기하면 Int, UInt 간에도 비교가능하도록 만드는 프로토콜
// (타입이 다름에도 비교가 가능)

let x1: Int = -7
let y1: UInt = 7


if x1 <= y1 {
    print("\(x1)가 \(y1)보다 작거나 같다.")
} else {
    print("\(x1)가 \(y1)보다 크다.")
}



// 실제로는 Int가 BinaryInteger 프로토콜을 채택
// Int에 기본구현으로 squared() 메서드가 제공  ===>  func squared() -> Int {..}


7.squared()

 

프로토콜의 확장은 구현의 반복을 줄이기 위한 문법이고

거기안에 메서드에서 반환하는 타입자체를 Self로 지칭하는걸 볼 수 있습니다

 

 

이렇게 self와 Self에 대해서 알아보았습니다

 

❤️혹시나 잘못된 부분이 있다면 댓글로 알려주면 감사하겠습니다❤️

 

 

 

 

✏️참고

앨런스위프트 문법 자료(강의) - ⭐️추천

반응형