🔥 인스턴스 메서드

918자
11분

인스턴스 메서드는 특정 클래스, 구조체 또는 열거형의 인스턴스에 속하는 함수입니다. 인스턴스 메서드는 인스턴스 속성에 접근하고 수정하는 방법을 제공하거나, 인스턴스의 목적과 관련된 기능을 제공함으로써 해당 인스턴스의 기능을 지원합니다. 인스턴스 메서드는 함수에 설명된 것과 정확히 동일한 문법을 가지고 있어요.

인스턴스 메서드는 해당 메서드가 속한 타입의 중괄호 안에 작성됩니다. 인스턴스 메서드는 해당 타입의 다른 모든 인스턴스 메서드와 속성에 암시적으로 접근할 수 있죠. 인스턴스 메서드는 해당 메서드가 속한 타입의 특정 인스턴스에서만 호출될 수 있습니다. 기존 인스턴스 없이 독립적으로 호출될 수는 없어요.

다음은 어떤 동작이 발생한 횟수를 세는 데 사용할 수 있는 간단한 Counter 클래스를 정의하는 예시입니다:

class Counter {
    var count = 0 // 현재 카운트 값을 저장하는 변수
 
    func increment() {
        count += 1 // 카운트를 1 증가시킴
    }
 
    func increment(by amount: Int) {
        count += amount // 카운트를 지정된 정수 값만큼 증가시킴
    }
 
    func reset() {
        count = 0 // 카운트를 0으로 초기화함
    }
}
swift

Counter 클래스는 세 가지 인스턴스 메서드를 정의합니다:

  • increment()는 카운터를 1 증가시킵니다.
  • increment(by: Int)는 카운터를 지정된 정수 값만큼 증가시킵니다.
  • reset()은 카운터를 0으로 초기화합니다.

Counter 클래스는 또한 현재 카운터 값을 추적하기 위해 count라는 변수 속성을 선언하고 있네요.

인스턴스 메서드는 속성과 동일한 점 표기법으로 호출됩니다:

let counter = Counter()
// 초기 카운터 값은 0입니다.
counter.increment()
// 카운터 값은 이제 1입니다.
counter.increment(by: 5)
// 카운터 값은 이제 6입니다.
counter.reset()
// 카운터 값은 이제 0입니다.
swift

함수 매개변수는 Function Argument Labels and Parameter Names에 설명된 대로 함수 내부에서 사용하기 위한 이름과 함수를 호출할 때 사용하기 위한 인자 레이블을 모두 가질 수 있습니다. 메서드는 타입과 연관된 함수이기 때문에 메서드 매개변수에도 동일한 규칙이 적용되죠.

self 속성

타입의 모든 인스턴스에는 self라는 암시적 속성이 있는데, 이는 인스턴스 자체와 정확히 동일합니다. self 속성을 사용하여 인스턴스 메서드 내에서 현재 인스턴스를 참조할 수 있어요.

위 예제의 increment() 메서드는 다음과 같이 작성될 수도 있습니다:

func increment() {
    self.count += 1 // self를 명시적으로 사용하여 count 속성 참조
}
swift

그러나 실제로는 코드에서 self를 자주 작성할 필요가 없습니다. self를 명시적으로 작성하지 않으면, 메서드 내에서 알려진 속성이나 메서드 이름을 사용할 때마다 Swift는 현재 인스턴스의 속성이나 메서드를 참조하고 있다고 가정합니다. 이 가정은 Counter의 세 인스턴스 메서드 내에서 count를 사용할 때 (self.count 대신) 입증되었죠.

이 규칙의 주요 예외는 인스턴스 메서드의 매개변수 이름이 해당 인스턴스의 속성 이름과 동일한 경우에 발생합니다. 이 상황에서는 매개변수 이름이 우선되며, 속성을 보다 명확한 방식으로 참조해야 해요. self 속성을 사용하여 매개변수 이름과 속성 이름을 구별하는 거죠.

다음 예제에서 selfx라는 메서드 매개변수와 x라는 인스턴스 속성을 구분합니다:

struct Point {
    var x = 0.0, y = 0.0
 
    func isToTheRightOf(x: Double) -> Bool {
        return self.x > x
        // self를 사용하여 인스턴스의 x 속성과 매개변수 x를 구별함
    }
}
 
let somePoint = Point(x: 4.0, y: 5.0)
 
if somePoint.isToTheRightOf(x: 1.0) {
    print("이 점은 x == 1.0인 선의 오른쪽에 있습니다.")
}
// "이 점은 x == 1.0인 선의 오른쪽에 있습니다."를 출력함
swift

self 접두사가 없다면 Swift는 x의 두 사용 모두 x라는 메서드 매개변수를 참조한다고 가정할 것입니다.

인스턴스 메서드 내에서 값 타입 수정하기

구조체와 열거형은 값 타입입니다. 기본적으로 값 타입의 속성은 인스턴스 메서드 내에서 수정될 수 없어요.

하지만 특정 메서드 내에서 구조체나 열거형의 속성을 수정해야 한다면, 해당 메서드에 대해 mutating 동작을 선택할 수 있습니다. 그러면 메서드는 메서드 내에서 속성을 변경(즉, 수정)할 수 있고, 메서드가 종료될 때 수행한 모든 변경 사항이 원래 구조체에 다시 기록되죠. 또한 메서드는 암시적 self 속성에 완전히 새로운 인스턴스를 할당할 수 있고, 이 새 인스턴스는 메서드가 종료될 때 기존 인스턴스를 대체합니다.

이 동작을 선택하려면 해당 메서드의 func 키워드 앞에 mutating 키워드를 배치하면 됩니다:

struct Point {
    var x = 0.0, y = 0.0
 
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        x += deltaX // x 좌표를 deltaX만큼 이동
        y += deltaY // y 좌표를 deltaY만큼 이동
    }
}
 
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveBy(x: 2.0, y: 3.0)
print("점의 좌표는 이제 (\(somePoint.x), \(somePoint.y))입니다.")
// "점의 좌표는 이제 (3.0, 4.0)입니다."를 출력함
swift

위의 Point 구조체는 Point 인스턴스를 일정 크기만큼 이동시키는 변경 가능한 moveBy(x:y:) 메서드를 정의합니다. 이 메서드는 새로운 점을 반환하는 대신 호출된 점을 실제로 수정하죠. mutating 키워드가 속성 수정을 가능하게 하기 위해 메서드 정의에 추가되었습니다.

Stored Properties of Constant Structure Instances에 설명된 대로, 구조체 타입의 상수에서는 변경 가능한 메서드를 호출할 수 없습니다. 속성이 변수 속성이라 하더라도 변경될 수 없기 때문이죠:

let fixedPoint = Point(x: 3.0, y: 3.0)
fixedPoint.moveBy(x: 2.0, y: 3.0)
// 이 코드는 에러를 보고할 것입니다.
swift

변경 가능한 메서드 내에서 self에 할당하기

변경 가능한 메서드는 암시적 self 속성에 완전히 새로운 인스턴스를 할당할 수 있습니다. 위에 보여진 Point 예제는 다음과 같이 작성될 수도 있어요:

struct Point {
    var x = 0.0, y = 0.0
 
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        self = Point(x: x + deltaX, y: y + deltaY)
        // 새로운 좌표로 self에 새 인스턴스 할당
    }
}
swift

이 버전의 변경 가능한 moveBy(x:y:) 메서드는 xy 값이 대상 위치로 설정된 새로운 구조체를 생성합니다. 이 대체 버전의 메서드를 호출한 결과는 이전 버전을 호출한 것과 정확히 동일할 거예요.

열거형의 변경 가능한 메서드는 암시적 self 매개변수를 동일한 열거형의 다른 case로 설정할 수 있습니다:

enum TriStateSwitch {
    case off, low, high
 
    mutating func next() {
        switch self {
        case .off:
            self = .low
        case .low:
            self = .high
        case .high:
            self = .off
        }
    }
}
 
var ovenLight = TriStateSwitch.low
ovenLight.next()
// ovenLight는 이제 .high와 같습니다.
ovenLight.next()
// ovenLight는 이제 .off와 같습니다.
swift

이 예제는 3단계 스위치에 대한 열거형을 정의합니다. 스위치는 next() 메서드가 호출될 때마다 세 가지 서로 다른 전원 상태(off, low, high) 사이를 순환하죠.

인스턴스 메서드는 클래스, 구조체, 열거형의 인스턴스에 기능을 추가하는 유용한 방법입니다. 특히 변경 가능한 메서드를 사용하면 구조체와 열거형의 값을 간편하게 수정할 수 있어요. 또한 self 속성을 활용하여 인스턴스 내에서 속성과 메서드 매개변수를 명확하게 구별할 수 있답니다.