Instance Property VS Type Property
Property(속성, 프로퍼티)는 형식(구조체, 클래스, 열거형 등)내부에 변수나 상수 키워드를 사용해 선언된 멤버입니다.
메모리 공간을 가지는 저장속성과 메모리 공간을 가지지 않는 계산 속성으로 나뉘어 집니다.
계산속성은 다른 속성에 저장된 값을 읽어서(다른 값에 의존적) 필요한 계산을 실행한 다음 값을 리턴합니다.
struct Age {
let birthday: Int // 저장 인스턴스 프로퍼티
var age: Int { // 계산(Computed) 인스턴스 프로퍼티
let year = Calendar.current.component(.year, from: Date())
return year - (birthday - 1)
}
}
let logan = Age(birthday: 1992)
logan.age
인스턴스에 속한 속성이기 때문에 인스턴스를 통해 접근할 수 있고, 인스턴스가 생성될 때마다 새로운 메모리 공간이 생성됩니다.
Type Property(타입 속성)는 조금 다릅니다. 우선 변수나 상수 키워드 앞에 static 키워드를 추가해줍니다. 타입 자체에 속한 속성이기 때문에 타입이름을 통해서만 접근이 가능하며 모든 인스턴스가 공유하는 하나의 공간만 생성합니다.
속성에 최초로 접근하는 시점에 메모리 공간이 생성됩니다.
Instance method VS Type method
특정 형식에 속한 함수를 메소드(method)라고 부릅니다.
속성의 차이처럼 인스턴스 메소드라면 인스턴스를 통해 호출해야하고 타입 메소드라면 타입을 통해 호출해야합니다.
예제
struct Circle {
var pi = Double.pi
var r: Double
func area() -> Double { pi * pow(r, 2) }
func perimeter() -> Double { 2 * pi * r }
}
var circle = Circle(r: 10)
circle.area() // 314.1592653589793
circle.perimeter() // 62.83185307179586
이해하기 쉽게 Circle이라는 형식을 만들었습니다. 그리고 pi 인스턴스 속성을 선언하고 Double.pi로 초기화 해주었습니다.
Double.pi
초기값으로 입력된 Double.pi에서 pi는 타입 이름으로 접근하고 있습니다.
(이 부분에서도 pi는 Double이 제공하는 타입 속성이라는 걸 유추할 수 있습니다.)
그리고 반지름(radius)을 나타내는 인스턴스 속성 r도 선언해주었습니다.
이어서 넓이(area)와 원의 둘레(perimeter)를 구하는 메소드 두 개를 추가했습니다.
그리고 circle 인스턴스를 생성한 다음, 인스턴스를 통해 각 멤버에 접근했습니다.
인스턴스 메소드에선, 자유롭게 인스턴스 속성을 사용할 수 있습니다.
struct Circle {
static let pi = Double.pi
// var r: Double
static func area(radius: Double) -> Double { pi * pow(radius, 2) }
static func perimeter(radius: Double) -> Double { 2 * pi * radius }
}
Circle.area(radius: 10) // 314.1592653589793
Circle.perimeter(radius: 10) // 62.83185307179586
원의 넓이나 둘레를 구하는 공식은 원의 반지름을 제외하면 바뀌지 않습니다.
그래서 이번엔 타입 멤버로 코드를 바꿔봤습니다.
static 키워드를 추가해 속성과 메소드를 변경해주었습니다.
메소드를 보면 차이가 있습니다.
메소드 내부에선, 인스턴스 멤버를 직접적으로 가져올 수 없습니다.
다시 말해, 반지름으로 사용하기 위해 선언했던 r 인스턴스 속성값은, 타입 메소드 area(radius:) 내부에선 직접 사용할 수 없습니다.
해당 멤버를 주석처리를 해주고, 메소드에 파라미터(radius: Double)를 추가해 반지름의 빈자리를 채워주었습니다.
멤버 접근 방식에도 차이가 있습니다. 인스턴스를 생성하지 않고, 타입 이름을 통해 멤버에 바로 접근합니다.
결과는 위와 다르지 않습니다.
TIP
pow 함수를 사용하면 x에 y만큼 제곱한 수를 리턴해줍니다.
func pow(_ x: Decimal, _ y: Int) -> Decimal
pow(1, 10) // 1
pow(2, 10) // 1024