Swift: 인스턴스 메서드(Instance Method)
스위프트에서는 클래스, 구조체, 열거형등의 동작을 캡슐화한 인스턴스 메서드와
타입 자체의 동작을 수행하는 타입 메서드를 정의할 수 있다.
구조체와 열거형이 메서드를 가질 수 있다는 점은 스위프트와 다른 프로그래밍 언어의 차별화된 장점이다.
스위프트는 프로그래머가 정의하는 타입(클래스, 구조체, 열거형 등)에 자유롭게 메서드를 정의할 수 있다.
인스턴스 메서드(instance method)
특정 타입의 인스턴스에 속한 함수를 말한다. 인스턴스와 관련된 동작을 수행한다.
문법은 함수와 동일하다.
인스턴스 메서드는 함수와 달리 특정 타입 내부에 구현하므로, 인스턴스가 존재할 때만 사용할 수 있다는 점이 함수와의 유일한 차이점이다.
class LevelClass {
//현재 레벨을 저장하는 저장 프로퍼티
var level: Int = 0 {
didSet {
print("Level \(level)")
}
}
//레벨이 올랐을 때 호출할 메서드
func levelUp() {
print("Level up!")
level += 1
}
//레벨이 감소 했을 때 호출할 메서드
func levelDown() {
print("Level down!")
level -= 1
if level < 0 {
reset()
}
}
func jumpLevel(to: Int) {
print("Jump to level \(to)")
level = to
}
func reset() {
print("Reset!")
level = 0
}
}
var levelClassInstance: LevelClass = LevelClass()
levelClassInstance.levelUp()
//Level up!
//Level 1
levelClassInstance.levelDown()
//Level down!
//Level 1
levelClassInstance.levelDown()
//Level down!
//Level -1
//Reset!
//Level 0
levelClassInstance.jumpLevel(to: 3)
//Jump to level 3
//Level 3
LevelClass의 인스턴스 메서드에 level 인스턴스 프로퍼티의 값을 수정하는 코드가 있다.
위처럼 클래스에서는 인스턴스의 프로퍼티 값을 수정할 때 크게 신경 쓸 필요가 없지만, 구조체와 열거형 타입은 값 타입이므로 앞에 mutating 키워드를 붙여서 해당 메서드가 인스턴스 내부의 값을 변경한다는 것을 명시해야 한다.
값 타입인 구조체와 열거형 내부의 프로퍼티 값을 메서드에서 수정하려면 메서드에 mutating 키워드를 붙여야 한다.
struct levelStrcut {
var level: Int = 0{
didSet {
print("Level \(level)")
}
}
mutating func levelUp() {
print("Level Up!")
level += 1
}
mutating func levelDown() {
print("Level Down")
level -= 1
if level < 0 {
reset()
}
}
mutating func jumpLevel(to: Int) {
print("Jump to \(to)")
level = to
}
mutating func reset() {
print("Reset!")
level = 0
}
}
self 프로퍼티
모든 인스턴스는 암시적으로 생성된 self 프로퍼티를 갖는다. 자바의 this처럼 인스턴스 자기 자신을 가리키는 프로퍼티이다. 메서드의 매개변수인지, 인스턴스의 프로퍼티인지 구분하는 등 좀 더 명확히 지정하고 싶을 때 사용한다.
class LevelClass {
var level: Int = 0
func jumpLevel(to level: Int) {
print("Jump to \(level)")
self.level = level
}
}
또한 self 프로퍼티를 이용해서 값 타입 인스턴스 자체의 값을 치환할 수 있다.
클래스의 인스턴스는 참조 타입이므로, self 프로퍼티에 다른 참조를 할당할 수 없지만 구조체나 열거형등은 self 프로퍼티를 사용하여 자신 자체를 치환할 수도 있다.
callAsFunction 메서드
사용자 정의 명목 타입의 호출 가능한 값(Callable values of user-defined nominal types)을 구현하기 위해 인스턴스를 함수처럼 호출할 수 있도록 하는 메서드(call-as-function method)가 있다.
특정 타입의 인스턴스를 문법적으로 함수를 사용하는 것처럼 보이게 할 수 있는데, callAsFunction이라는 이름의 메서드를 구현해 인스턴스를 함수처럼 호출할 수 있다.
struct Puppy {
var name: String = "댕댕이"
func callAsFunction() {
print("댕댕~")
}
func callAsFunction(destination: String) {
print("댕댕이가 \(destination)으로 갑니다~")
}
func callAsFunction(something: String, times: Int) {
print("댕댕이가 \(something)을 \(times)번 반복합니다.")
}
func callAsFunction(color: String) -> String {
return "\(color) 응가"
}
mutating func callAsFunction(name: String) {
self.name = name
}
}
var doggy: Puppy = Puppy()
doggy.callAsFunction() //댕댕~
doggy() //댕댕~ -> 인스턴스를 함수처럼 사용하고 있다.
doggy.callAsFunction(destination: "집") //댕댕이가 집으로 갑니다~
doggy(destination: "뒷동산") //댕댕이가 뒷동산으로 갑니다~
doggy(something: "공중제비", times: 3) //댕댕이가 공중제비을 3번 반복합니다.
print(doggy(color: "무지개색")) //무지개색 응가
doggy(name: "멍멍이")
print(doggy.name) //멍멍이
doggy() 표현과 doggy.callAsFunction()은 완전히 똑같은 표현이다.
마찬가지로 doggy(destination: "집")과 doggy.callAsFunction(destination: "집")은 완전히 동일한 표현이 된다.
하지만 호출하는 것 외에 타입처럼 함수 표현으로는 사용할 수 없음에 주의하자.
let function: (String) -> Void = doggy(destination:) //불가능
let function: (String) -> Void = doggy.callAsFunction(destination:) //가능