메서드(Method)는 특정 타입에 관련된 함수를 뜻한다.
타입 자체와 관련된 기능을 실행하는 타입 메서드를 정의할 수도 있는데 이는 기존의 프로그래밍 언어에서의 클래스 메서드와 유사한 개념이다.
구조체와 열거형이 메서드를 가질 수 있다는 건 기존 프로그래밍 언어와 swift간의 큰 차이점이다. 프로그래머가 정의하는 타입 예를 들어 클래스, 구조체, 열거형 등에 자유롭게 메서드를 정의할 수 있다.
인스턴스 메서드는 말 그대로 특정 타입의 인스턴스에 속한 함수를 뜻한다. 인스턴스 내부의 프로퍼티 값을 변경하거나 특정 연산 결과를 반환하는 등 인스턴스와 관련된 기능을 실행하는데 함수와 문법은 같지만, 함수와 달리 특정 타입 내부에 구현한다. 따라서 인스턴스가 존재할 때만 사용할 수 있다.
클래스의 인스턴스 메서드를 정의하고 사용하는 방법은 다음과 같다.
class AgeClass {
// 현재 나이를 저장하는 저장 프로퍼티
var age: Int = 24 {
// 프로퍼티 값이 변경되면 호출하는 프로퍼티 감시자
didSet {
print("나이: \(age)")
}
}
func NewYear() {
age += 1
print("한살 더 먹었습니다.")
}
}
var myAgeClassInstance: AgeClass = AgeClass()
myAgeClassInstance.NewYear()
결과
나이: 25
한살 더 먹었습니다.
위와 같이 프로퍼티 값을 수정할 때 클래스의 인스턴스 메서드는 크게 신경쓸 필요가 없다.
만약, 구조체나 열거형 등의 값 타입이라면?
메서드 앞에 mutating 키워드를 붙여서 해당 메서드가 인스턴스 내부의 값을 변경한다는 것을 명시해야 한다.
구조체의 인스턴스 메서드를 정의하고 사용하는 방법은 다음과 같다.
struct AgeClass {
var age: Int = 24 {
didSet {
print("나이: \(age)")
}
}
mutating func NewYear() {
age += 1
print("한살 더 먹었습니다.")
}
}
var myAgeClassInstance: AgeClass = AgeClass()
myAgeClassInstance.NewYear()
결과
나이: 25
한살 더 먹었습니다.
모든 인스턴스는 암시적으로 생성된 self 프로퍼티를 갖는다. 자바의 this와 비슷하게 인스턴스 자기 자신을 가리키는 프로퍼티이다.
예를 들어, 메서드 매개변수의 이름이 age인데, 이 age 매개변수가 아닌 인스턴스 프로퍼티인 age를 지칭하고 싶다면 self 프로퍼티를 사용한다.
self 프로퍼티를 사용하는 방법은 다음과 같다.
var age: Int = 24
func NewYear(age: Int) {
self.age += 1
print("한살 더 먹었습니다.")
}
또한, self 프로퍼티는 값 타입 인스턴스 자체의 값을 치환할 수 있다. 클래스의 인스턴스는 참조 타입이라서 self 프로퍼티에 다른 참조를 할당할 수 없는 거에 비해서 구조체나 열거형 등은 self 프로퍼티를 사용하여 자신 자체를 치환할 수도 있다.
특정 타입의 인스턴스를 문법적으로 함수를 사용하는 것처럼 보이게 할 수 있다.
인스턴스를 함수처럼 호출할 수 있도록 하려면 callAsFunction이라는 메서드를 구현하면 된다. 이 메서드는 매개변수와 반환 타입만 다르다면 원하는 만큼 만들 수 있다.
mutating, throws, rethrows를 함께 사용할 수 있다.
callAsFunction 메서드 구현 방법은 다음과 같다.
struct Puppy {
var name: String = "흰둥이"
func callAsFunction() {
print("멍멍")
}
func callAsFunction(destination: String) {
print("\(destination)으로 달려갑니다.")
}
}
var myPuppy:Puppy = Puppy()
myPuppy.callAsFunction()
myPuppy()
myPuppy.callAsFunction(destination: "집")
myPuppy(destination: "집")
결과
멍멍
멍멍
집으로 달려갑니다.
집으로 달려갑니다.
인스턴스 프로퍼티와 타입 프로퍼티가 있듯이 메서드에도 인스턴스 메서드와 타입 메서드가 있다.
타입 자체에 호출이 가능한 메서드를 타입 메서드라고 부르는데 메서드 앞에 static 키워드를 사용한다.
클래스의 타입 메서드는 static 키워드와 class 키워드를 사용할 수 있는데 static으로 정의하면 상속 후 메서드 재정의가 불가능하고, class로 정의하면 상속 후 메서드 재정의가 가능하다.
아래와 같이 클래스가 정의되어 있다고 생각해보자.
class AClass {
static func staticTypeMethod() {
print("AClass staticTypeMethod")
}
class func classTypeMethod() {
print("AClass classTypeMethod")
}
}
위에서 static으로 정의된 메서드를 상속 후 메서드를 재정의한다면? 에러를 내뱉게 됨을 알 수 있다.
class BClass: AClass{
override static func staticTypeMethod() {
}
}
결과
Cannot override static method
위에서 class로 정의된 메서드를 상속 후 메서드를 재정의한다면? 가능함을 알 수 있다.
class BClass: AClass {
override class func classTypeMethod() {
}
}