Methods

Groot·2022년 8월 24일
0

Swift Language Guide

목록 보기
11/24
post-thumbnail

Methods

  • 메소드는 특정 유형과 연관된 함수입니다.
  • class, struct 및 enum은 모두 주어진 유형의 인스턴스로 작업하기 위한 특정 작업 및 기능을 캡슐화하는 인스턴스 메서드를 정의할 수 있습니다.
  • class, struct 및 enum은 형식 자체와 연결된 형식 메서드를 정의할 수도 있습니다.
  • 타입 메소드는 Objective-C의 class 메소드와 유사합니다.
  • struct와 enum이 Swift에서 메서드를 정의할 수 있다는 사실은 C 및 Objective-C와의 주요 차이점입니다.
  • Objective-C에서 class는 메소드를 정의할 수 있는 유일한 유형입니다.
  • Swift에서는 class, struct 또는 enum을 정의할지 여부를 선택할 수 있으며 생성한 유형에 대해 메서드를 정의할 수 있는 유연성이 있습니다.

📌 Instance Methods

  • 인스턴스 메서드는 특정 class, struct 또는 enum의 인스턴스에 속하는 함수입니다.
  • 인스턴스 속성에 액세스하고 수정하는 방법을 제공하거나 인스턴스의 목적과 관련된 기능을 제공하여 해당 인스턴스의 기능을 지원합니다.
  • 속해 있는 유형의 여는 중괄호와 닫는 중괄호 안에 인스턴스 메서드를 작성합니다.
  • 인스턴스 메서드는 해당 유형의 다른 모든 인스턴스 메서드 및 속성에 대한 암시적 액세스 권한을 가집니다.
  • 인스턴스 메소드는 그것이 속한 유형의 특정 인스턴스에서만 호출할 수 있습니다.
  • 기존 인스턴스 없이는 별도로 호출할 수 없습니다.
    class Counter {
        var count = 0
        func increment() {
            count += 1
        }
        func increment(by amount: Int) {
            count += amount
        }
        func reset() {
            count = 0
        }
    }
  • Counter class는 세 가지 인스턴스 메서드를 정의합니다.
    • increment()는 카운터를 1씩 증가시킵니다.
    • increment(by: Int)는 지정된 정수 양만큼 카운터를 증가시킵니다.
    • reset()은 카운터를 0으로 재설정합니다.
  • Counter class는 현재 카운터 값을 추적하기 위해 count라는 변수 속성으로 선언합니다.
    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
  • 함수 매개변수는 함수 인수 레이블 및 매개변수 이름에 설명된 대로 이름(함수 본문 내에서 사용)과 인수 레이블(함수를 호출할 때 사용)을 모두 가질 수 있습니다.
  • 메서드는 Type과 연결된 함수일 뿐이므로 메서드 매개변수의 경우에도 마찬가지입니다.

📍 The self Property

  • 유형의 모든 인스턴스에는 인스턴스 자체와 정확히 동일한 self라는 암시적 속성이 있습니다.
  • self 속성을 사용하여 자체 인스턴스 메서드 내에서 현재 인스턴스를 참조합니다.
  • 위의 예에서 increment() 메서드는 다음과 같이 작성할 수 있습니다.
    func increment() {
        self.count += 1
    }
  • 실제로 코드에 self를 자주 작성할 필요는 없습니다.
  • 명시적으로 self를 작성하지 않으면 Swift는 메서드 내에서 알려진 속성이나 메서드 이름을 사용할 때마다 현재 인스턴스의 속성이나 메서드를 참조하고 있다고 가정합니다.
  • 이 가정은 Counter에 대한 세 가지 인스턴스 메서드 내에서 (self.count가 아닌) count를 사용하여 입증됩니다.
  • 이 규칙의 주요 예외는 인스턴스 메소드의 매개변수 이름이 해당 인스턴스의 속성과 동일한 이름을 가질 때 발생합니다.
  • 이 경우 매개변수 이름이 우선하며 보다 한정된 방식으로 속성을 참조해야 합니다.
  • self 속성을 사용하여 매개변수 이름과 속성 이름을 구별합니다.
    struct Point {
        var x = 0.0, y = 0.0
        func isToTheRightOf(x: Double) -> Bool {
            return self.x > x
        }
    }
    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"
  • self 접두사가 없으면 Swift는 x의 두 사용 모두 x라는 메서드 매개변수를 참조한다고 가정합니다.

📍 Modifying Value Types from Within Instance Methods

  • struct와 enum은 값 유형입니다.
  • 기본적으로 값 유형의 속성은 인스턴스 메서드 내에서 수정할 수 없습니다.
  • 그러나 특정 메서드 내에서 struct 또는 enum의 속성을 수정해야 하는 경우 해당 메서드에 대한 동작을 변경하도록 선택할 수 있습니다.
  • 그런 다음 메서드는 메서드 내에서 속성을 변경(즉, 변경)할 수 있으며 변경 사항은 메서드가 종료될 때 원래 struct에 다시 기록됩니다.
  • 이 메서드는 암시적 self 속성에 완전히 새로운 인스턴스를 할당할 수도 있으며 이 새 인스턴스는 메서드가 종료되면 기존 인스턴스를 대체합니다.
  • 해당 메소드의 func 키워드 앞에 mutating 키워드를 배치하여 이 동작을 선택할 수 있습니다.
    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)"
  • 위의 Point struct는 특정 양만큼 Point 인스턴스를 이동하는 변형 moveBy(x:y:) 메서드를 정의합니다.
  • 이 메서드는 새 포인트를 반환하는 대신 실제로 호출된 포인트를 수정합니다.
  • mutating 키워드는 속성을 수정할 수 있도록 정의에 추가됩니다.
  • 상수 struct 인스턴스의 저장된 속성에 설명된 대로 struct 유형의 상수에 대해 변경 메서드를 호출할 수 없습니다.
  • 그 속성은 가변 속성이더라도 변경할 수 없기 때문입니다.
    let fixedPoint = Point(x: 3.0, y: 3.0)
    fixedPoint.moveBy(x: 2.0, y: 3.0)
    // this will report an error

📍 Assigning to self Within a Mutating Method

  • 메서드를 변경하면 암시적 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)
        }
    }
  • 이 버전의 mutating moveBy(x:y:) 메서드는 x 및 y 값이 대상 위치로 설정된 새 struct를 생성합니다.
  • 이 대체 버전의 메서드를 호출한 최종 결과는 이전 버전을 호출할 때와 정확히 동일합니다.
  • enum에 대한 변경 메서드는 암시적 자체 매개변수를 동일한 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
  • 이 예는 3-상태 스위치에 대한 열거를 정의합니다. 스위치는 next() 메서드가 호출될 때마다 세 가지 다른 전원 상태(꺼짐, 낮음 및 높음) 사이를 순환합니다.

📌 Type Methods

  • 위에서 설명한 것처럼 인스턴스 메서드는 특정 유형의 인스턴스에서 호출하는 메서드입니다.

  • 유형 자체에서 호출되는 메소드를 정의할 수도 있습니다. 이러한 종류의 메소드를 유형 메소드라고 합니다.

  • 메소드의 func 키워드 앞에 static 키워드를 작성하여 유형 메소드를 나타냅니다.

  • class는 대신 class 키워드를 사용하여 하위 class가 해당 메서드의 상위 class 구현을 재정의할 수 있도록 할 수 있습니다.

    Objective-C에서는 Objective-C class에 대해서만 유형 수준 메서드를 정의할 수 있습니다. Swift에서는 모든 class, struct 및 enum에 대한 유형 수준 메서드를 정의할 수 있습니다. 각 형식 메서드는 지원하는 형식으로 명시적으로 범위가 지정됩니다.

  • 유형 메소드는 인스턴스 메소드와 같은 점 구문으로 호출됩니다. 그러나 해당 유형의 인스턴스가 아니라 유형에서 유형 메소드를 호출합니다.

  • SomeClass라는 class에서 유형 메서드를 호출하는 방법은 다음과 같습니다.

    class SomeClass {
        class func someTypeMethod() {
            // type method implementation goes here
        }
    }
    SomeClass.someTypeMethod()
  • 형식 메서드의 본문 내에서 암시적 self 속성은 해당 형식의 인스턴스가 아니라 형식 자체를 참조합니다.

  • 즉, 인스턴스 속성 및 인스턴스 메서드 매개변수와 마찬가지로 self를 사용하여 형식 속성과 형식 메서드 매개변수를 구분할 수 있습니다.

  • 보다 일반적으로 형식 메서드의 본문 내에서 사용하는 정규화되지 않은 메서드 및 속성 이름은 다른 형식 수준 메서드 및 속성을 참조합니다.

  • 타입 메서드는 타입 이름을 접두사로 붙일 필요 없이 다른 메서드의 이름으로 다른 타입 메서드를 호출할 수 있습니다.

  • 유사하게, struct 및 enum의 유형 메서드는 유형 이름 접두사 없이 유형 속성의 이름을 사용하여 유형 속성에 액세스할 수 있습니다.

  • 아래 예는 게임의 여러 레벨 또는 단계를 통해 플레이어의 진행 상황을 추적하는 LevelTracker라는 struct를 정의합니다.

  • 싱글 플레이어 게임이지만 단일 장치에 여러 플레이어의 정보를 저장할 수 있습니다.

  • 게임을 처음 플레이할 때 게임의 모든 레벨(레벨 1 제외)이 잠겨 있습니다.

  • 플레이어가 레벨을 완료할 때마다 장치의 모든 플레이어에 대해 해당 레벨이 잠금 해제됩니다.

  • LevelTracker struct는 유형 속성과 메서드를 사용하여 잠금 해제된 게임 레벨을 추적합니다.

  • 또한 개별 플레이어의 현재 레벨을 추적합니다.

        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
                }
            }
        }
  • LevelTracker struct는 모든 플레이어가 잠금 해제한 최고 레벨을 추적합니다.

  • 이 값은 highUnlockedLevel이라는 유형 속성에 저장됩니다.

  • LevelTracker는 또한 highUnlockedLevel 속성과 함께 작동하는 두 가지 유형 함수를 정의합니다.

  • 첫 번째는 새로운 레벨이 잠금 해제될 때마다 highUnlockedLevel의 값을 업데이트하는 unlock(_:)이라는 유형 함수입니다.

  • 두 번째는 isUnlocked(_:)라는 편의 유형 함수로, 특정 레벨 번호가 이미 잠금 해제되어 있으면 true를 반환합니다.

  • (이러한 유형 메서드는 LevelTracker.highestUnlockedLevel로 작성할 필요 없이 highUnlockedLevel 유형 속성에 액세스할 수 있습니다.)

  • 유형 속성 및 유형 메서드 외에도 LevelTracker는 게임을 통해 개별 플레이어의 진행 상황을 추적합니다.

  • currentLevel이라는 인스턴스 속성을 사용하여 플레이어가 현재 재생 중인 레벨을 추적합니다.

  • currentLevel 속성 관리를 돕기 위해 LevelTracker는 advance(to:)라는 인스턴스 메서드를 정의합니다.

  • currentLevel을 업데이트하기 전에 이 메서드는 요청된 새 수준이 이미 잠금 해제되어 있는지 확인합니다.

  • Advance(to:) 메서드는 부울 값을 반환하여 실제로 currentLevel을 설정할 수 있는지 여부를 나타냅니다.

  • Advance(to:) 메서드를 호출하는 코드가 반환 값을 무시하는 것은 반드시 실수가 아니기 때문에 이 함수는 @discardableResult 속성으로 표시됩니다.

  • LevelTracker struct는 아래와 같이 Player class와 함께 사용되어 개별 플레이어의 진행 상황을 추적하고 업데이트합니다.

    class Player {
        var tracker = LevelTracker()
        let playerName: String
        func complete(level: Int) {
            LevelTracker.unlock(level + 1)
            tracker.advance(to: level + 1)
        }
        init(name: String) {
            playerName = name
        }
    }
  • Player class는 해당 플레이어의 진행 상황을 추적하기 위해 LevelTracker의 새 인스턴스를 만듭니다.

  • 또한 플레이어가 특정 레벨을 완료할 때마다 호출되는 complete(level:) 메서드를 제공합니다.

  • 이 방법은 모든 플레이어의 다음 레벨을 잠금 해제하고 플레이어의 진행 상황을 업데이트하여 다음 레벨로 이동합니다.

  • (advance(to:)의 부울 반환 값은 무시됩니다.

  • 이전 줄에서 LevelTracker.unlock(_:) 호출에 의해 레벨이 잠금 해제된 것으로 알려져 있기 때문입니다.)

  • 새 플레이어를 위한 Player class의 인스턴스를 만들고 플레이어가 레벨 1을 완료하면 어떻게 되는지 확인할 수 있습니다.

    var player = Player(name: "Argyrios")
    player.complete(level: 1)
    print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
    // Prints "highest unlocked level is now 2"
  • 게임의 어떤 플레이어도 아직 잠금 해제하지 않은 레벨로 이동하려고 하는 두 번째 플레이어를 생성하면 플레이어의 현재 레벨 설정 시도가 실패합니다.

    player = Player(name: "Beto")
    if player.tracker.advance(to: 6) {
        print("player is now on level 6")
    } else {
        print("level 6 hasn't yet been unlocked")
    }
    // Prints "level 6 hasn't yet been unlocked"
profile
I Am Groot

0개의 댓글