메서드 (Methods)

메서드는 특정 유형과 관련된 함수입니다. 클래스, 구조체 및 열거형은 모두 지정된 유형의 인스턴스 작업을 위한 특정 작업 및 기능을 캡슐화하는 인스턴스 메서드를 정의 할 수 있습니다. 클래스, 구조체 및 열거형은 유형 자체와 연관된 유형 메소드를 정의 할 수도 있습니다. 형식 메서드는 Objective-C의 클래스 메서드와 유사합니다.

구조체와 열거형이 Swift에서 메소드를 정의를 할 수 있다는 사실은 C 및 Objective-C와의 주요 차이점입니다. Objective-C에서 클래스는 메서드를 정의 할 수있는 유일한 유형입니다. Swift에서는 클래스, 구조체 또는 열거형을 정의할지 여부를 선택할 수 있으며 생성 한 유형에 대한 메서드를 유연하게 정의 할 수 있습니다.

Instance Methods
인스턴스 메서드

인스턴스 메서드는 특정 클래스, 구조체 또는 열거형의 인스턴스에 속하는 함수입니다. 인스턴스 프로퍼티에 액세스하고 수정하는 방법을 제공하거나 인스턴스의 목적과 관련된 기능을 제공하여 해당 인스턴스의 기능을 지원합니다. 인스턴스 메서드는 함수에 설명 된대로 함수와 정확히 동일한 구문을 갖습니다.

해당 유형의 여는 중괄호{와 닫는 중괄호} 안에 인스턴스 메서드를 작성합니다. 인스턴스 메서드에는 다른 모든 인스턴스 메서드와 해당 유형의 프로퍼티에 대한 암시 적 액세스 권한이 있습니다. 인스턴스 메서드는 자신이 속한 유형의 특정 인스턴스에서만 호출 할 수 있습니다. 기존 인스턴스 없이는 격리 된 상태로 호출 할 수 없습니다.

다음은 작업이 발생한 횟수를 계산하는 데 사용할 수있는 간단한 Counter 클래스를 정의하는 예입니다.

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

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

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

Counter 클래스는 현재 카운터 값을 추적하기 위해 변수 속성 인 count도 선언합니다.

프로퍼티와 동일한 점 구문을 사용하여 인스턴스 메서드를 호출합니다.

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

함수 매개 변수는 함수 인수 레이블 및 매개 변수 이름에 설명 된대로 이름 (함수 본문 내에서 사용)과 인수 레이블 (함수 호출시 사용)을 모두 가질 수 있습니다. 메서드는 형식과 관련된 함수일 뿐이므로 메서드 매개 변수도 마찬가지입니다.

The self Property
self 프로퍼티

타입의 모든 인스턴스에는 self라는 암시 적 프로퍼티가 있으며 이는 인스턴스 자체와 정확히 동일합니다. self 프로퍼티를 사용하여 자체 인스턴스 메서드 내에서 현재 인스턴스를 참조합니다.

위의 예에서 increment () 메서드는 다음과 같이 작성할 수 있습니다.

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

실제로 코드에 self를 자주 작성할 필요는 없습니다. self를 명시 적으로 작성하지 않으면 Swift는 메서드 내에서 알려진 프로퍼티 또는 메서드 이름을 사용할 때마다 현재 인스턴스의 프로퍼티 또는 메서드를 참조한다고 가정합니다. 이 가정은 Counter의 세 가지 인스턴스 메서드 내에서 count (self.count가 아닌)를 사용하여 입증됩니다.

이 규칙의 주요 예외는 인스턴스 메서드의 매개 변수 이름이 해당 인스턴스의 프로퍼티와 동일한 이름을 가질 때 발생합니다. 이 상황에서는 매개 변수 이름이 우선하므로 더 규정 된 방식으로 특성을 참조해야합니다. self 프로퍼티를 사용하여 매개 변수 이름과 프로퍼티 이름을 구분합니다.

여기에서 self는 x라는 메서드 매개 변수와 x라고도하는 인스턴스 프로퍼티을 명확하게합니다.

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 ( "이 지점은 x == 1.0 인 줄의 오른쪽에 있습니다.")
}

Modifying Value Types from Within Instance Methods
인스턴스 메서드 내에서 값 유형 수정

구조체와 열거형은 값 유형입니다. 기본적으로 값 유형의 프로퍼티는 인스턴스 메서드 내에서 수정할 수 없습니다.

그러나 특정 메서드 내에서 구조체 또는 열거형의 프로퍼티를 수정해야하는 경우 해당 메서드의 동작을 변경하도록 선택할 수 있습니다. 그런 다음 메서드는 메서드 내에서 프로퍼티를 변경 (즉, 변경) 할 수 있으며, 메서드가 종료 될 때 변경된 사항은 원래 구조체에 다시 기록됩니다. 메서드는 암시 적 자체 프로퍼티에 완전히 새로운 인스턴스를 할당 할 수도 있으며 이 새 인스턴스는 메서드가 종료 될 때 기존 인스턴스를 대체합니다.

해당 메서드의 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 ( "이제 포인트는 (\ (some Point.x), \ (somePoint.y))")

위의 Point 구조는 Point 인스턴스를 일정량 이동하는 mutating moveBy (x : y : ) 메서드를 정의합니다. 새 포인트를 반환하는 대신이 메서드는 실제로 호출 된 포인트를 수정합니다. mutating 키워드는 프로퍼티를 수정할 수 있도록 정의에 추가됩니다.

상수 구조 인스턴스의 저장된 프로퍼티에 설명 된대로 변수 속성 인 경우에도 속성을 변경할 수 없기 때문에 구조체 유형의 상수에 대해 mutating 메서드를 호출 할 수 없습니다.

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
Mutating 메서드 내에서 자신에게 할당

변경 메서드는 암시 적 자체 프로퍼티에 완전히 새로운 인스턴스를 할당 할 수 있습니다. 위에 표시된 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 값이 대상 위치로 설정된 새 구조를 만듭니다. 이 대체 버전의 메서드를 호출 한 최종 결과는 이전 버전을 호출 할 때와 정확히 동일합니다.

열거형을 변경하는 메서드는 암시 적 자체 매개 변수를 동일한 열거형과 다른 케이스로 설정할 수 있습니다.

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와 같습니다.
오븐 Light.next ()
// ovenLight는 이제 .off와 같습니다.

이 예에서는 3 개 상태 스위치에 대한 enum을 정의합니다. 스위치는 next () 메서드가 호출 될 때마다 세 가지 전원 상태 (꺼짐, 낮음 및 높음) 사이를 순환합니다.

Type Methods
타입 메서드

위에서 설명한대로 인스턴스 메서드는 특정 유형의 인스턴스에서 호출하는 메서드입니다. 유형 자체에서 호출되는 메소드를 정의 할 수도 있습니다. 이러한 종류의 메서드를 타입 메서드라고합니다. 메서드의 func 키워드 앞에 static 키워드를 작성하여 타입 메서드를 나타냅니다. 클래스는 대신 class 키워드를 사용하여 하위 클래스가 해당 메서드의 수퍼 클래스 구현을 재정의 할 수 있습니다.

  • static 함수 — override 불가능
  • class 함수 — override 가능

final class function {} 와 static function {} 둘다 재정의 할 수 없음

NOTE
Objective-C에서는 Objective-C 클래스에 대해서만 유형 수준 메서드를 정의 할 수 있습니다. Swift에서는 모든 클래스, 구조체 및 열거형에 대한 유형 수준 메서드를 정의 할 수 있습니다. 각 형식 메서드는 지원하는 형식으로 명시 적으로 범위가 지정됩니다.

타입 메서드는 인스턴스 메서드와 같이 점 구문으로 호출됩니다. 그러나 해당 유형의 인스턴스가 아닌 유형에 대해 타입 메서드를 호출합니다. SomeClass라는 클래스에서 타입 메소드를 호출하는 방법은 다음과 같습니다.

class SomeClass {
    class func someTypeMethod() {
        // 타입 메소드 구현은 여기에
    }
}
SomeClass.someTypeMethod()

타입 메서드의 본문 내에서 암시 적 self 프로퍼티는 해당 형식의 인스턴스가 아닌 타입 자체를 참조합니다. 즉, 인스턴스 프로퍼티 및 인스턴스 메서드 매개 변수에 대해 수행하는 것처럼 self를 사용하여 타입 프로퍼티와 타입 메서드 매개 변수를 명확하게 할 수 있습니다.

일반적으로 타입 메서드 본문 내에서 사용하는 정규화되지 않은 메서드 및 프로퍼티 이름은 다른 타입의 수준 메서드 및 프로퍼티를 참조합니다. 타입 메소드는 타입 이름을 접두어로 사용 할 필요 없이 다른 메소드의 이름으로 다른 타입 메소드를 호출 할 수 있습니다. 마찬가지로 구조체 및 열거형의 타입 메서드는 타입 이름 접두사 없이 타입 프로퍼티의 이름을 사용하여 파입 프로퍼티에 액세스 할 수 있습니다.

아래 예는 게임의 다양한 레벨 또는 단계를 통해 플레이어의 진행 상황을 추적하는 LevelTracker라는 구조체를 정의합니다. 싱글 플레이어 게임이지만 단일 기기에 여러 플레이어의 정보를 저장할 수 있습니다.

게임을 처음 플레이 할 때 모든 게임 레벨 (1 레벨 제외)이 잠 깁니다. 플레이어가 레벨을 완료 할 때마다 해당 레벨은 장치의 모든 플레이어에게 잠금 해제됩니다. LevelTracker 구조체는 타입 프로퍼티와 메서드를 사용하여 잠금 해제 된 게임 레벨을 추적합니다. 또한 개별 플레이어의 현재 레벨을 추적합니다.

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 구조체는 모든 플레이어가 잠금을 해제 한 최고 레벨을 추적합니다. 이 값은 highestUnlockedLevel이라는 프로퍼티에에 저장됩니다.

LevelTracker는 또한 higherUnlockedLevel 프로퍼티와 함께 작동하는 두 가지 타입 함수를 정의합니다. 첫 번째는 unlock (_ : )이라는 타입 함수로, 새 레벨이 잠금 해제 될 때마다 highestUnlockedLevel 값을 업데이트합니다. 두 번째는 isUnlocked (_ : )라는 convenience 타입 함수로, 특정 레벨 번호가 이미 잠금 해제 된 경우 true를 반환합니다. (이러한 타입 메서드는 LevelTracker.highestUnlockedLevel로 작성할 필요없이 highestUnlockedLevel 타입 프로퍼티에 액세스 할 수 있습니다.)

타입 프로퍼티 및 타입 메서드 외에도 LevelTracker는 게임을 통해 개별 플레이어의 진행 상황을 추적합니다. currentLevel이라는 인스턴스 프로퍼티를 사용하여 플레이어가 현재 재생중인 레벨을 추적합니다.

currentLevel 프로퍼티를 관리하기 위해 LevelTracker는 advance (to : )라는 인스턴스 메서드를 정의합니다. currentLevel을 업데이트하기 전에 이 메서드는 요청 된 새 레벨이 이미 잠금 해제되었는지 여부를 확인합니다. advance (to : ) 메서드는 실제로 currentLevel을 설정 할 수 있는지 여부를 나타내는 부울 값을 반환합니다. advance (to : ) 메서드를 호출하여 반환 값을 무시하는 코드가 반드시 실수는 아니기 때문에이 함수는 @discardableResult 속성으로 표시됩니다. 이 속성에 대한 자세한 내용은 속성을 참조하십시오.

LevelTracker 구조는 아래에 표시된 Player 클래스와 함께 사용되어 개별 플레이어의 진행 상황을 추적하고 업데이트합니다.

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 클래스는 해당 플레이어의 진행 상황을 추적하기 위해 LevelTracker의 새 인스턴스를 만듭니다. 플레이어가 특정 레벨을 완료 할 때마다 호출되는 complete (level : ) 메서드도 제공합니다. 이 방법은 모든 플레이어의 다음 레벨을 잠금 해제하고 플레이어의 진행 상황을 업데이트하여 다음 레벨로 이동합니다. (이전 행에서 LevelTracker.unlock (_ : ) 호출에 의해 레벨이 잠금 해제 된 것으로 알려져 있으므로 advance (to : )의 Boolean 반환 값은 무시됩니다.)

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

var player = Player(name: "Argyrios")
player.complete(level: 1)
print ( "잠금 해제 된 최고 레벨은 이제 \ (LevelTracker.highestUnlockedLevel)")
// "잠금 해제 된 최고 레벨은 이제 2"를 인쇄합니다.

게임에서 아직 잠금 해제되지 않은 레벨로 이동하려는 두 번째 플레이어를 만드는 경우 해당 플레이어의 현재 레벨 설정 시도는 실패합니다.

player = Player(name: "Beto")
if player.tracker.advance(to: 6) {
    print ( "플레이어가 이제 레벨 6에 있습니다.")
} else {
    print ( "레벨 6은 아직 잠금 해제되지 않았습니다.")
}
// "레벨 6이 아직 잠금 해제되지 않았습니다"를 인쇄합니다.

에 발행했습니다
SWIFT(으)로 분류되었습니다

aaron님이 작성

아무것도 안해도 시간은 흐른다.

댓글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다