Properties
특정 인스턴스와 연관있는 값
Keyword
- Stored Properties
- Lazy Stored Properties
- Computed Properties
- Property Observers
- Type Properties
1. Stored Properties
- Class, Struct 에서 사용 가능
- var 사용하면 변수 저장 프로퍼티
- let 사용하면 상수 저장 프로퍼티
'Stored Properties' of struct
변수 저장 프로퍼티인 name
과 상수 저장 프로퍼티인 age
struct PersonStruct {
var name: String
let age: Int
}
var person = PersonStruct(name: "a", age: 2)
person.name = "b"
person.age = 1 // Error 발생
- 만약 var person을 let으로 바꾸면 어떻게 될까요?
struct PersonStruct {
var name: String
let age: Int
}
let person = PersonStruct(name: "a", age: 2)
person.name = "b" // Error 발생
person.age = 1 // Error 발생
name 부분에서 에러가 발생합니다. 그 이유는 Sturct이 Call by Value 이기 때문입니다. 레퍼런스에 접근할 수 없습니다.
'Stored Properties' of class
class PersonClass {
var name: String
let age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
var person = PersonClass(name: "a", age: 2)
person.name = "b"
person.age = 1 // Error 발생
- 위에서 실험해본 것 처럼 var person을 let으로 바꾸면 어떻게 될까요?
class PersonClass {
var name: String
let age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
let person = PersonClass(name: "a", age: 2)
person.name = "b"
person.age = 1 // Error 발생
문제 없이 이름이 바뀝니다.
2. Lazy Stored Properties
- struct, class 에만 사용 가능
- computed property 에는 사용할 수 없다.
- 값이 사용되기 전 까지 계산되지 않는 프로퍼티이다.
- 맨 앞에 lazy 라는 키워드를 붙여준다
- 무조건 var 사용
- 주의 할 점은 thread-safety 하지 않아서 여러번 초기화가 발생할 수 있다.
- 지연 저장 프로퍼티를 잘 사용하면 불필요한 성능 저하나 공간 낭비를 줄일 수 있다.
class Sample {
lazy var module = SampleModule()
}
var sample = Sample()
sample.module.run() // 이제서야 module 이 생성된다.
lazy and closure
- lazy에 어떤 특별한 연산을 통해 값을 넣어주기 위해 코드 실행 블록인 closure를 사용한다.
- lazy 키워드가 붙으면 closure내에서 self로 접근이 가능하다. 일반적으로는 절때 불가능하다. (당연한 이야기)
- 클래스 내부의 클로저에서 클래스 객체를 self 로 참조한다면 메모리 누수가 발생하는 위험이 있다
아래 코드는 뒤의 ()를 통해 그 즉시 실행하고 결과를 돌려주기 때문에 메모리 누수의 걱정은 없다 (그 대신 메모리에 한번 올라간 name 이 변경되지 않는다)
class Person {
var name:String
lazy var greeting:String = {
return "Hello my name is \((self.name))"
}()
init(name:String){
self.name = name
}
}
var me = Person(name:"John")
print(me.greeting // Hello my name is John
me.name = "James"
print(me.greeting // Hello my name is John
참고로 self 에 weak self 지정하면 업데이트 된 name 이 출력된다.
값이 아닌 클로저 자체가 메모리에 올라가 있고 self 는 내부에서 계속해서 클래스를 참조하기 때문에 계속 John이 출력이 되는 것이 아닌 James가 출력이 되는 것
class Person {
var name:String
lazy var greeting: ()->String = { [weak self] in
return "Hello my name is \(((self?.name))!)"
}
init(name:String){
self.name = name
}
}
var me = Person(name:"John")
print(me.greeting()) // Hello my name is John
me.name = "James"
print(me.greeting()) // Hello my name is James
3. Computed Property
- class, struct, enumeraion 모두 사용 가능하다
- 연산 프로퍼티는 실제 값을 저장하는 프로퍼티가 아니라, 특정 상태에 따른 값을 연산하는 프로퍼티이다.
- getter, setter 역할을 수행할 수 있다.
왜 메서드를 사용하지 않고 연산 프로퍼티를 사용하는가?
- 프로퍼티가 메서드 형식보다 훨씬 더 간편하고 직관적이다.
- 다만, 주의해야될 점은 연산 프로퍼티는 접근자인 get메서드처럼 읽기 전용을 구현하기 쉽지만, 쓰기 전용은 구현할 수 없다는 단점이 있다.(메서드로는 가능하지만 프로퍼티로는 불가능)
메서드 방식
struct CoordinatePoint {
var x: Int
var y: Int
// 대칭점을 구하는 메서드 - 접근자(getter)
func oppsitePoint() -> CoordinatePoint {
return CoordinatePoint(x: -x, y: -y)
}
mutating func setOppositePoint(_ opposite: CoordinatePoint) {
x = -opposite.x
y = -opposite.y
}
}
var position: CoordinatePoint = CoordinatePoint(x: 10, y: 20)
//현재 좌표
print(position)
//대칭 좌표
print(position.oppsitePoint())
//대칭 좌표를 (15, 10)으로 설정
position.setOppositePoint(CoordinatePoint(x: 15, y: 10))
print(position) // -15, -10
연산 프로퍼티
struct CoordinatePoint {
var x: Int
var y: Int
var oppsitionPoint: CoordinatePoint {
get {
return CoordinatePoint(x: 10, y: 20)
}
// set {
// x = -newValue.x
// y = -newValue.y
// }
set (someParam) {
x = -someParam.x
y = -someParam.y
}
}
}d
4. Property Observers
- 오로지 저장 프로퍼티에만 적용 가능하다
- 말 그대로 프로퍼티 변경을 감시한다
- 새로 값이 할당될때마다 호출되며 값이 같아도 호출된다.
class Account {
var credit: Int = 0 {
willSet {
print("잔액이 \(credit)에서 \(newValue)원으로 변경될 예정입니다.")
}
didSet {
print("잔액이 \(oldValue)에서 \(credit)으로 변경되었습니다.")
}
}
}
let myAccount: Account = Account()
myAccount.credit = 1000
5. Type Properties
- 각각 인스턴스가 아닌 타입 자체에 속하게 되는 프로퍼티
- 타입 프로퍼티는 타입 자체에 영향을 미치는 프로퍼티, 저장이나 연산은 인스턴스마다 다를 수 있다
- 무조건 1만 리턴하는 경우
참고자료
'iOS > Swift' 카테고리의 다른 글
Struct and class (0) | 2020.09.07 |
---|
댓글