본문 바로가기
Swift 공식 가이드/Swift 3

Methods

by 토끼찌짐 2017. 3. 1.

Apple 제공 Swift 프로그래밍 가이드(3.0.1)의 Methods 부분을 공부하며 정리한 글입니다. 개인적인 생각도 조금 들어가있습니다.



들어가며

메서드(method)란 특정 타입에 연관된 함수(function)를 말한다. 클래스, 구조체, ENUM은 인스턴스 메서드와 타입 메서드(Objective-C에서의 클래스 메서드)를 정의할 수 있다.

Swift에서는 구조체와 ENUM 안에도 메서드를 정의할 수 있다는 것이 C, Objective-C와의 주요 차이점이라고 할 수 있다.


Instance Methods

인스턴스 메서드는 특정 클래스, 구조체, ENUM의 인스턴스에 속하는 메서드이다. 함수와 같은 문법을 사용한다.

class Counter {
    var count = 0
    func increment() {
        count += 1
    }
    func increment(by amount: Int) {
        count += amount
    }
    func reset() {
        count = 0
    }
}

let counter = Counter() // 0
counter.increment() // 1
counter.increment(by: 5) // 6
counter.reset() // 0

참고로 함수 단원에서 배웠던 parameter name, argument label 의 규칙이 메서드에도 동일하게 적용된다. (메서드는 "타입에 연관된 함수"임)


<The self Property>

모든 인스턴스는 self 라는 프로퍼티를 가진다. 인스턴스 자신을 가리키는 참조이다. self 프로퍼티는 인스턴스 메서드내에서 현재 자신(인스턴스)을 참조할 때 쓰일 수 있다.

func increment() {
    // 이런 식으로
    self.count += 1
}


그러나 딱히 self를 쓰지 않더라도 인스턴스 메서드 안에서 변수/상수 이름을 사용하면 self 내의 변수/상수임을 가정해주므로 별로 쓸 일은 없다. 그러나 메서드의 파라미터 이름과 인스턴스 프로퍼티 이름이 겹칠 경우에는 써야 한다.

struct Point {
    var x = 0.0, y = 0.0
    func isToTheRightOf(x: Double) -> Bool {
        return self.x > x
    }
}


<Modifying Value Types from Within Instance Methods>

값 타입의 프로퍼티는 인스턴스 메서드 안에서 값을 그냥은 변경할 수가 없다. 값 타입인 구조체와 ENUM의 인스턴스 메서드 안에서 프로퍼티의 값을 변경하려면 꼭 mutating 라는 키워드를 메서드 앞에 붙여야 한다.

struct Point {
    var x = 0.0, y = 0.0
    mutating func moveBy(x deltaX: Double, y deltaY:Double) {
        x += deltaX
        y += deltaY
       // mutating function 이기 때문에 성공
    }
}

var somePoint = Point(x: 1.0, y: 1.0) // (1.0, 1.0)
somePoint.moveBy(x: 2.0, y: 3.0) // (3.0, 4.0)

let fixedPoint = Point(x: 3.0, y: 3.0)
fixedPoint.moveBy(x: 2.0, y: 3.0) // compile error
// mutating 메서드는 let으로 선언된 인스턴스에서 사용불가


<Assigning to self Within a Mutating Method>

mutating 메서드에서 self 자체에 새로운 인스턴스를 대입하면 인스턴스 자체에 새로운 인스턴스를 할당 가능하다.

// struct의 경우
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)
    }
}

// enum의 경우
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 is now equal to .high
ovenLight.next()
// ovenLight is now equal to .off"

위와 같이 인스턴스 메서드 내에서 self에 할당을 하는 것은 값타입인 구조체/ENUM만 가능하다. 클래스의 경우 mutating 메서드 자체를 정의할 수 없으며 (할 필요가 없으며)  클래스의 인스턴스 메서드 안에서 self에 할당을 하려고 하면 self는 immutable이라며 에러가 난다.



Type Methods

Objective-C에서의 클래스 메서드같이 타입 그 자체에 속하는 메서드이다.

문법은 타입 프로퍼티와 유사하다. 메서드 앞에 static 키워드를 붙여서 정의한다. 클래스의 타입 메서드의 경우 static 대신 class 키워드를 붙이면, 서브클래스에게 해당 타입 메서드의 오버라이드를 허락할 수 있다. (반대로 붙이지 않으면 오버라이드 불가)

<note> Objective-C에서는 타입 레벨의 메서드를 오직 Objective-C Class에만 정의할 수 있었다. 그러나 Swift에서는 타입 레벨의 메서드를 모든 클래스, 구조체, ENUM에 정의할 수 있다.

class SomeClass {
    static func someTypeMethod() {
        
    }
    
    class func someOverridableTypeMethod() {
    
    }
}

class SomeChildClass: SomeClass {
    override static func someTypeMethod() {
        // compile error
    }
    
    override class func someOverridableTypeMethod() {
        // OK
    }
}

SomeClass.someTypeMethod() //  호출은 이렇게 타입에 대고 한다


타입 메서드 안에서는 자기 타입에 정의된 다른 타입 프로퍼티나 타입 메서드를 참조할 때 타입 이름을 쓰지 않아도 된다. (인스턴스 메서드 안에서도 self를 명시하지 않아도 알아서 self 내의 프로퍼티를 찾아주는 것과 동일한 원리이다. 타입 메서드 안에서의 self는 어차피 타입 그 자체이기 때문에)

struct LevelTracker {
    static var highestUnlockedLevel = 1
    static func unlock(_ level: Int) {
        if level > highestUnlockedLevel {
            highestUnlockedLevel = level
            
            // LevelTracker.highestUnlockedLevel 로 접근하지 않아도 된다는 것
        }
    }
}


'Swift 공식 가이드 > Swift 3' 카테고리의 다른 글

Inheritance  (0) 2017.03.01
Subscripts  (0) 2017.03.01
Properties  (0) 2017.02.27
Classes and Structures  (0) 2017.02.27
Enumerations  (0) 2017.02.27