서문
- 메소드는 함수에 포함되는 하위개념. Class/Struct/enum에 포함되어 있는 함수를 메소드 혹은 클래스 함수라고 부른다.
- 메소드도 인스턴스 메소드 / 타입 메소드가 있을 수 있다
- 참고로 Objective-C를 포함한 C-like 언어에서는 Struct와 enum에서 인스턴스/타입 메소드를 만들 수 없다. Swift의 flexability
인스턴스 메소드
- 개념
- 생성된 특정 인스턴스에 대한 메소드 (=생성하지 않으면 호출불가)
- 구문형태는 Function와 완전히 동일하다
- 어떤 인스턴스 메소드든 all other 인스턴스 메소드와 프로퍼티에 별도의 작업이나 구문없이 바로 접근할 수 있다
- 예제
참고로 아래 예제는 참조타입인 class이므로 바로 프로퍼티 변경 또한 가능하다
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
- Self Property
- 모든 인스턴스는 self라는 암시적 프로퍼티를 가지고 있고 이는 인스턴스 자기 자신을 의미한다
- 인스턴스 메소드에서 인스턴스 자신을 참조하고 싶을 때 사용될 수 있다
- 사실 위의 예제처럼 Type 내에 정의된 프로퍼티나 메소드에 접근할 때는 self를 붙이지 않아도 Swift가 알아서 current instance에 접근함을 알 수 있다
- 그렇지 않은 예제를 살펴보자 - self가 반드시 필요한 경우
struct Point { var x = 0.0, y = 0.0 func isToTheRightOf(x: Double) -> Bool { return self.x > x //self없이 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"
- 메소드에서 값타입 프로퍼티도 수정하기
- 우선, 메소드 내에서 current instance에 접근할 수 있는 이유는 인스턴스 자기자신을 parameter(self)로 암시적 전달하기 때문이다
- (메소드도 함수이므로) 함수에서는 전달받은 parameter가 값타입이면 copy기반이기 때문에 바꿔도 의미없고 바꿔지지도 않는다 (컴파일 에러)
- 기존에 함수 내에서 parameter 원본값을 바꾸기 위해선 inout키워드를 사용하였다. 유사하게 메소드에서는 mutating 키워드를 활용할 수 있다
- 그리고 당연하지만, 상수로 선언된 인스턴스는 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)"
- self 바꿔버리기
- 우리는 mutating으로 값타입인 struct와 enum에서도 프로퍼티를 변경할 수 있다
- 놀라운건 entire 자기자신(self)조차 new Instance로 바꿀 수도 있다
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)"
- 열거형에서 유용하게 사용될 것 같은 느낌이 든다
enum TriStateSwitch { case off, low, high mutating func next() { switch self { case .off: self = .low case .low: self = .high case .high: self = .off } } }
타입 메소드
- 개념
- 인스턴스 메소드는 어떤 타입으로 생성한 인스턴스 하나에 대해 동작하는 반면, 타입 메소드는 어떤 타입 자체에 대해 동작한다
- 사용
- 일반적으로 static keyword로 사용할 수 있다
- Swift에서 Class는 (struct와 달리) 하나 정도는 상속이 가능하다는 특징이 있다
상속받은 자식 Class에서 타입 메소드를 overriding(재정의)하고 싶은 경우에는 static이 아닌 class로 prefix를 주어 재정의 가능여부를 구분한다
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 } //return값을 사용하지 않아도 warning을 출력하지 않는 attribute @discardableResult mutating func advance(to level: Int) -> Bool { if LevelTracker.isUnlocked(level) { currentLevel = level return true } else { return false } } } 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 } } 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"
- 특징
- 인스턴스는 타입 메소드를 호출할 수 없다
- 타입 메소드에서의 self는 인스턴스가 아닌 타입 자체를 참조하며 타입 프로퍼티에는 이름 prefix없이 바로 접근가능하다
- 타입 프로퍼티는 값타입인 struct/enum에서도 mutating없이 self를 변경할 수 있다. 인스턴스 프로퍼티는 명백히 값타입이지만 타입 프로퍼티는 그렇지 않은가보다
'Swift > Language Guide' 카테고리의 다른 글
Initialization - #2/2 (0) | 2021.09.13 |
---|---|
Initialization - #1/2 (0) | 2021.09.13 |
Properties - #1/1 (0) | 2021.09.12 |
Structures and Classes - #1/1 (0) | 2021.09.12 |
Control Flow - #2/2 (0) | 2021.09.12 |
댓글