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
복사