Search

[Swift 공식 문서] 11. Methods

Methods

메서드란 특정 타입에 연관된 함수입니다. 클래스, 구조체, 열거형에서 인스턴스 메서드를 사용할 수 있습니다.
1.
인스턴스 메서드 : 인스터스에 대한 여러 기능을 캡슐화 한 함수
2.
타입 메서드 : 타입에 대한 여러 기능을 캡슐화 한 함수
Objective - C 에서는 클래스에서만 메서드를 정의할 수 있습니다면, Swift 에서는 클래스 구조체 열거형 모두에서 메서드를 사용할 수 있습니다.

Instance Methods

인스턴스 메서드는 특정 클래스, 구조체, 열거형에 속한 함수입니다. 인스턴스에 여러 기능을 부여할 수 있으며, 인스턴스의 프로퍼티 또한 변경과 수정이 가능합니다. 사용 방법은 함수와 동일합니다.
타입의 중괄호 내에서 함수를 선언함으로써 인스턴스 메서드를 만들 수 있습니다. 인스턴스 메서드는 같은 타입에 속한 인스턴스 메서드와 프로퍼티에 대한 암묵적인 접근 권한을가집니다.
인스턴스 메서드는 속한 타입의 인스턴스에서 호출될 수 있습니다. 인스턴스 없이 호출이 불가능함에 주의하세요
class Counter { var count = 0 func increment() { count += 1 } func increment(by amount: Int) { count += amount } func reset() { count = 0 } }
Swift
복사
Counter 클래스는 3개의 인스턴스 메서드를 가지고 있습니다.
increment() : 카운터를 1 증가시킵니다
increment(by: Int) : 카운터를 특정 정수 값만큼 증가시킵니다
reset() : 카운터를 0 으로 초기화합니다
Counter 클래스는 현재 카운터 값을 조사하기 위한 변수 프로퍼티 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
Swift
복사
함수의 파라미터는 이름과 argument lable 을 둘다 보유할 수 있으며, 각각의 역할은 함수와 동일합니다.

The self Property

모든 타입의 인스턴스는 암묵적인 프로퍼티인 self 를 가집니다. 이 self 는 인스턴스 자신과 동일합니다.
self 프로퍼티를 사용해서 현재 인스턴스를 참조할 수 있습니다.
func increment() { self.count += 1 }
Swift
복사
self 프로퍼티를 항상 사용해야하는 것은 아닙니다. 만약 self 를 생략한다면, Swift는 메서드 내의 메서드 이름, 프로퍼티를 현재 인스턴스의 메서드, 프로퍼티로 참조합니다. 따라서 대부분의 경우에 self 는 생략이 가능합니다.
self 를 반드시 사용해야하는 경우는 메서드의 파라미터 이름과 해당 메서드가 속한 타입 내에 파라미터 이름과 동일한 프로퍼티가 존재할 때 입니다. 이 경우 Swift 는 self 를 사용하지 않으면 파라미터로 인식하고, self 를 사용하면 인스턴스의 프로퍼티로 인식합니다. 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"
Swift
복사
위 예시에서 만약 self 키워드를 생략한다면 두 x 를 모두 파라미터로 인식합니다.

Modifying Value Types from Within Instance Methods

구조체와 열거형은 value type 입니다.
value type의 프로퍼티 값은 인스턴스 메서드 내에서 수정이 불가능합니다. ( 클래스는 가능 )
구조체나 열거형의 프로퍼티를 특정 메서드내에서 변경하고자 한다면, 메서드에 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)"
Swift
복사
메서드가 실행 도중에 프로퍼티를 변경하는 것이 아니라, 메서드가 종료되면 인스턴스를 새 인스턴스로 대체합니다. 따라서 인스턴스를 상수로 선언하게 되면 해당 메서드를 사용할 수 없습니다.
let fixedPoint = Point(x: 3.0, y: 3.0) fixedPoint.moveBy(x: 2.0, y: 3.0) // this will report an error
Swift
복사

Assigning to self Within a Mutationg Method

새로운 인스턴스를 self 프로퍼티에 할당할 수 있습니다.
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) } }
Swift
복사
자기 자신에 새로운 인스턴스를 할당하는 것으로 아까와 동일한 결과가 나오게 됩니다. 열거형에서의 mutating 메서드와 self 를 아래와 같이 사용이 가능합니다.
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
Swift
복사

Type Methods

타입 메서드란 타입 자체에서 호출할 수 있는 메서드입니다. static 키워드를 사용해서 타입메서드를 사용할 수 있습니다. 클래스들은 class 키워드를 static 대신 사용해서 하위클래스에게 부모클래스의 메서드를 override 할 수 있도록 허가합니다.
Objective C 에서는 type level 메서드를 클래스에 대해서만 사용이 가능합니다. Swift 에서는 클래스 구조체 열거형에 타입 메서드 사용이 가능합니다.
타입 메서드는 인스턴스 메서드와 동일하게 . 을 통해 호출합니다. 하지만 인스턴스 이름이 아닌 이때 메서드가 존재하는 타입의 이름으로 호출해주어야합니다.
class SomeClass { class func someTypeMethod() { // type method implementation goes here } } SomeClass.someTypeMethod()
Swift
복사
타입 메서드의 body 안에서는 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 } } }
Swift
복사
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 } }
Swift
복사
Player 클래스는 LevelTracker 의 새 인스턴스를 생성하여 player 의 진행상황을 추적합니다. 또한 complete(level:) 라는 player 가 특적 level 을 클리어 하였을 때 사용하는 메서드를 제공합니다. 이메서드는 모든 플레이어에 대해 다음 level 을 개방하고 또한 player 의 진행상황을 다음 상황으로 옮깁니다. ( 이때 리턴값은 @dicardableResult 특성에 의해 무시될 수 있습니다.
Player 클래스의 인스턴스를 생성하여서 새 player 를 생성해봅시다.
var player = Player(name: "Argyrios") player.complete(level: 1) print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)") // Prints "highest unlocked level is now 2"
Swift
복사
두번째 플레이어를 생성하여서 이 플레이어를 level 6 으로 옮기려고 해도 이 level 은 아직 개방되어있지 않기 때문에, 이 시도는 실패합니다.
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"
Swift
복사