Method : 특정 type 과 관련있는 fuction.

Obj-C 에서는 class 만 method 를 정의할 수 있었지만 Swfit 에서는 class, struct, enum 모두 method 를 정의할 수 있음.

Instance Methods

Instance method : 특정 class/struct/enum 의 인스턴스에 속하는 function. Function 과 완전히 같은 문법을 가짐

Instance method 는 해당 타입의 모든 다른 instance method 와 property 에 대한 암묵적인 접근을 얻음. 속하는 type 의 instance 에서만 호출될 수 있으며 instance 없이 독립적으로 존재할 수 없음

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

let counter = Counter()
// the initial counter value is 0
counter.increment()
// the counter's value is now 1
counter.increment(by: 5)
// the counter's value is now 6
counter.reset()
// the counter's value is now 0

The self Property

특정 타입의 모든 instance 는 해당 instance 와 완전히 동일한 암묵적인 self property 를 가짐. Instance method 안에서 자신(instance) 를 참조할 수 있음.

실제로 self 를 직접 쓸 일은 많지 않음. 만약 명시적으로 self 를 쓰지 않는다면 Swift 는 method 안에서 property 나 method 를 호출할 때 해당 instance 의 property 나 method 를 쓴다고 가정함. 하지만 instance method 의 parameter 이름이 property 의 이름과 같은 경우에는 parameter 가 우선순위를 가지게 됨

func increment() {
    self.count += 1
}

struct Point {
    var x = 0.0, y = 0.0
    // parameter name == property name. Parameter 가 우선순위를 가짐
    func isToTheRightOf(x: Double) -> Bool {
        return self.x > x // 우측의 x 는 parameter
    }
}
let somePoint = Point(x: 4.0, y: 5.0)
if somePoint.isToTheRightOf(x: 1.0) {
    print("This point is to the right of the line where x == 1.0")
}
// Prints "This point is to the right of the line where x == 1.0".

Modifying Value Types from Within Instance Methods

Struct, enum 은 value type 으로, 기본적으로 value type 의 property 는 instance method 안에서 수정될 수 없음.

mutating 을 써서 method 내부에서 struct/enum 의 property 를 수정할 수 있게 할 수 있음

struct Point {
    var x = 0.0, y = 0.0
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        x += deltaX
        y += deltaY
    }
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveBy(x: 2.0, y: 3.0)
print("The point is now at (\(somePoint.x), \(somePoint.y))")
// Prints "The point is now at (3.0, 4.0)".

Assigning to self Within a Mutating Method

Mutating method 는 암묵적인 self property 에 완전히 새로운 instance 를 할당할 수도 있음.

아래와 같이 작성한느 것은 위의 mutating function 에서 property 를 바꾼 것과 완전히 같은 결과를 보여줌

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 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

Type Methods

static 키워드를 func 키워드 전에 써서 Type 자체에서 호출될 수 있는 method 를 정의 가능. Class 의 경우 class 키워드를 써서 subclass 가 superclass 의 type emthod 를 override 할 수 있게 함

class A {
    class func someFunction() {
        print("A")
    }
}

class B: A {
    override static func someFunction() {
        print("B")
    }
}

Type method 의 body 에서 암묵적 self property 는 type 자체를 말함. 이는 self 를 사용해서 type property 와 type method parameter 를 구분할 수 있음.

Type method 안에서 사용하는 method/property 이름은 기본적으로 다른 top-level(static) method/property 를 가리킴.

struct LevelTracker {
    static var highestUnlockedLevel = 1
    var currentLevel = 1


    static func unlock(_ level: Int) {
        if level > highestUnlockedLevel { highestUnlockedLevel = level }
    }


    static func isUnlocked(_ level: Int) -> Bool {
        return level <= highestUnlockedLevel
    }


    @discardableResult
    mutating func advance(to level: Int) -> Bool {
        if LevelTracker.isUnlocked(level) {
            currentLevel = level
            return true
        } else {
            return false
        }
    }
}