ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 메소드 (Methods)
    Swift 2020. 12. 8. 03:35

    특정 타입의 클래스, 구조체, 열거형과 관련된 함수를 메소드라고 합니다. 예를 들어, String에는 hasPrefix가 있습니다. 

    특정 타입의 인스턴스에서 실행할 수 있는 메소드를 인스턴스 메소드, 특정 형과 관련된 메소드를 타입 메소드라고 합니다.

    Swift에서는 클래스 뿐만 아니라 구조체, 열거형에서도 메소드를 사용할 수 있습니다.

     

    인스턴스 메소드 (Instance Methods)

    인스턴스 메소드는 클래스, 구조체, 열거형의 인스턴스에 속한 메소드입니다. 이 메소드를 통해서 인스턴스 내의 값을 다룰 수 있습니다. 인스턴스 메소드는 해당 인스턴스에서만 실행이 가능합니다.

    class Counter {
        var cnt = 0
        func increment {
            cnt += 1
        }
        func increment(by amount: Int){
            cnt += amount
        }
        func reset(){
            cnt = 0
        }
    }
    
    
    let counter = Counter()
    counter.increment()
    //cnt = 1
    counter.increment(by: 10)
    //cnt = 11
    counter.reset()
    //cnt = 0

    -> Counter 메소드에는 increment(), increment(by amount: Int), reset()을 정의해서 cnt 변수의 값을 변경합니다.

    self 프로퍼티 (The self Property)

    모든 프로퍼티는 인스턴스 자체를 의미하는 self라는 프로퍼티를 가집니다. 인스턴스 메소드 안에서 self를 이용해 인스턴스 자체를 참조하는데 사용할 수 있습니다.

    //1
    func increment(){
        self.cnt += 1
    }
    
    //2
    func increment(int cnt){
        self.cnt += 1
    }

    ->  //1 위의 Counter class의 increment()에서 사실 cnt += 1은 self.cnt += 1과 같은 의미입니다.

    -> // 2 만약 파라미터 값으로 같은 이름인 cnt를 가지면 self를 이용해서 명확하게 합니다.

     

    인스턴스 메소드 내에서 값 타입 변경 (Modifying Value Types from Within Instance Methods)

    구조체와 열거형의 메소드가 내부에서 데이터를 수정할 때에는 mutating키워드를 붙여야 합니다.

    struct Point {
        var x = 0, y = 0
        mutating func moveBy(x: Int, y: Int){
            self.x += x
            self.y += y
        }
    }
    
    var somePoint = Point(x: 1, y: 1)
    somePoint.moveBy(x: 10, y: 10)
    //somePoint.x = 11, somePoint.y = 11

    -> 위의 Point구조체에서, 원래는 인스턴스 메소드에서 프로퍼티를 변경하는 것이 불가능하지만 인스턴스 메소드 앞에 mutating이 붙어있으면 변경이 가능합니다. 

     

    Mutating 메소드 내에서 self 할당 (Assignming to self Withing a Mutating a Mutating Method)

    mutating 메소드에서 self 프로퍼티를 이용해 완전 새로운 인스턴스를 생성할 수 있습니다. 

    struct Point{
        var x = 0, y = 0
        mutating func moveBy(x delX: Int, y delY: Int){
            self = Point(x: x + delX, y: y + delY)
        }
    }
    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()
    // .high
    ovenLight.next()
    // .off

    -> ovenLight 인스턴스에서 next() 메소드를 이용해서 상태를 변경할 수 있습니다.

     

     

    타입 메소드 (Type Methods)

    타입 메소드는 특정 타입에서 호출해 사용합니다. 타입 메소드의 선언은 func앞에 static 또는 class 키워드를 추가합니다.

    둘의 차이점은 static 메소드는 서브클래스에서 오버라이드 할 수 없는 타입 메소드이고, class 메소드는 서브클래스에서 오버라이드 할 수 있는 메소드입니다.

     

    class SomeClass {
        class func someTypeMethod(){
        
        }
    }
    someClass.someTypeMethod()

    -> 타입 메소드는 점(.)문법으로 호출합니다. 하지만 인스턴스를 만들어서 호출하는 것이 아니라, 타입 이름으로 호출합니다.

    -> 타입 메소드 안에도 self 키워드를 사용할 수 있습니다. 여기서 self는 타입 자신을 의미합니다.

     

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

    -> 타입 메소드 안에도 self 키워드를 사용할 수 있습니다. 여기서 self는 타입 자신을 의미합니다.

    -> 또한 타입 메소드 안에서 다른 타입 메소드를 사용하는 것이 가능합니다.

    -> advance 앞의 @discardableResult 키워드는 리턴 값이 있는 메소드에서 리턴 값을 사용하지 않으면 컴파일러 경고가 발생하는데, 그 경고를 발생하지 않도록 합니다. xx..advance만 하면 return 값을 저장할 변수가 없지만 discardableResult(버릴 수 있는 결과)이므로 경고를 발생하지 않습니다. @discardableResult를 사용하지 않고, _ = xx.advance로 호출해도 됩니다.

     

    class Player{
        var tracker = LevelTracker()
        let playerName: String
        func complete(level: Int){
            LevelTracker.unlock(level + 1)
            tracker.advance(to: levle + 1)
        }
        init(name: String){
            playerName = name
        }
    }
    
    var player = Player(name: "Hee")
    player.complete(level: 1)
    print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
    //highest unlocked level is now 2 출력

     

     

     

     

     

    'Swift' 카테고리의 다른 글

    상속 (Inheritance)  (0) 2020.12.10
    클로저 (Closures)  (0) 2020.12.05
    클래스와 구조체 (Classes and Structures)  (0) 2020.11.10
    프로퍼티 (Properties)  (0) 2020.11.10
    열거형 (Enumerations)  (0) 2020.11.05

    댓글

Designed by Tistory.