티스토리 뷰

Swift

Swift) About Property

행복하고 싶은 사람 2022. 8. 10. 16:14

Swift 공식문서에서는 property를 이렇게 정의합니다. 

프로퍼티는 값을 특정 class, structure, enumeration과 연결시킨다. 저장 프로퍼티는 상수나 변수를 인스턴스 값으로 저장하고 

연산 프로퍼티는 저장하기보다 값을 계산합니다. 연산 프로퍼티는 class, struct, enum 모두에서 사용될 수 있으나 저장 프로퍼티는 enum에서는 사용 할 수 없다. 저장 프로퍼티와 연산 프로퍼티는 거의 특정 타입의 인스턴스와 연관이 있으나 프로퍼티는 타입 자체와 관련이 있을수도 있는데 이러한 프로퍼티를 타입 프로퍼티라고한다.

 

즉 프로퍼티에는 3가지 형태가 존재함

  • Stored Property: 저장 프로퍼티
  • Computed Property: 연산 프로퍼티
  • Type Property: 타입 프로퍼티

저장 프로퍼티

클래스와 구조체에서만 사용할 수 있고, 값을 저장하기 위해 선언되는 상수 또는 변수

class Human {
    let name: String = "unknown"
    var age: Int = 0
}
 
struct Person {
    let name: String = "unknown"
    var age: Int = 0
}

Human 클래스, Person 구조체의 name, age는 모두 저장 프로퍼티임

지연 저장 프로퍼티

프로퍼티가 호출되는 순간에 초기화 되는 저장 프로퍼티. 즉 호출되기 이전까지는 초기화X

class Contacts {
   var email: String = ""
   var address: String = ""
 
    init() { print("Contacts Init 🐙") }
}
 
class Human {
   var name: String = "unknown"
   var contacts: Contacts = .init()
}

let man : Human = .init()

클래스건 구조체건 인스턴스를 생성할 경우 initializer가 불리는 순간 모든 프로퍼티는 초기화 되어야함. 그러므로 man이란 인스턴스를 만들고 init을 호출한 순간 Human안에 있는 모든 프로퍼티들이 초기화되며 contacts도 초기화됨.

class Contacts {
   var email: String = ""
   var address: String = ""
 
    init() { print("Contacts Init 🐙") }
}
 
class Human {
   var name: String = "unknown"
   lazy var contacts: Contacts = .init()
}

let man: Human = .init()

contacts 앞에 lazy란 키워드를 붙이면 init을 해도 contacts가 초기화되지 않음.

man.contacts.address = "none"

그리고 이렇게 contacts란 변수에 처음 접근할때 초기화됨.

지연 저장 프로퍼티는 인스턴스의 초기화와 상관없이 처음 사용될 때 개별적으로 초기화되므로 항상 변수로 선언되어야함. 왜냐면 let으로 선언될 경우 원하는 시점에 초기화를 진행할 수 없기 때문!

근데 이걸 왜씀?

→ 잘 사용하면 성능도 향상되고 메모리 낭비도 줄일 수 있음.

참고 블로그:

Swift) 프로퍼티 정복하기 (1/4) - 저장 프로퍼티(Stored Property)

연산 프로퍼티

클래스, 구조체, 열거형에서 사용되고 저장 프로퍼티와 달리 저장 공간을 가지지않고 다른 저장 프로퍼티의 값을 읽어 연산을 실행하거나, 프로퍼티로 전달받은 값을 다른 저장 프로퍼티에 저장. 그러므로 항상 변수로 선언되어야 한다.

var name: Type {
    get {           //getter (다른 저장 연산프로퍼티의 값을 얻거나 연산하여 리턴할 때 사용)
        statements
        return expr
    }
    set(name) {     //setter (다른 저장프로퍼티에 값을 저장할 때 사용)
        statements
    }
}

이렇게 생간게 연산 프로퍼티의 기본형태

연산 프로퍼티는 어떠한 값을 저장하는게 아니기 때문에 타입 추론을 할 수가 없어서 선어할 때 반드시 타입 어노테이션을 통해 자료형을 명시해야함.

getter는 어떤 저장 프로퍼티의 값을 연산해서 return하는 것. 그러므로 return 구문이 항상 존재해야함.

class Person {
    var name: String = "man"
 
    var alias: String {
        get {
            return name
        }
        set(name) {
            self.name = name
        }
    }
}

이렇게 name과 같이 읽거나 쓸 수 있는 저장 프로퍼티가 반드시 존재해야 하고 연산 프로퍼티에서는 이 저장 프로퍼티의 값을 읽거나 쓰는 작업을 해야함.

연산 프로퍼티의 사용 방법

let man: Person = .init()

print(man.alias)

man.alias = "남자"
print(man.name) // 

연산 프로퍼티는 이렇게 저장 프로퍼티처럼 사용하면됨.

set의 파라미터는 생략해줄 수도 있는데 그러면 newValue라는 이름으로 접근할 수 있음.

set {
    self.name = newValue + "은 별명에서 지어진 이름"
}

연산 프로퍼티를 쓸때는 getter만 선언해줄 수도 있는데 이러면 get-only라고 함.

class Person {
    var name: String = "man"
 
    var alias: String {
        get {
            return self.name + "은 별명에서 지어진 이름"
        }
    }
}

이런 식으로 사용할 수 있는데 간단하게 하면

class Person {
    var name: String = "man"
 
    var alias: String {
       return self.name + "은 별명에서 지어진 이름"
    }
}

이렇게 사용될 수 있음.

이렇게 get-only는 있지만 set-only는 안됨. 그러므로 get, set을 같이 구현하거나 get-only로만 구현해야함.

타입 프로퍼티

클래스, 구조체, 열거형에서 사용됨.

저장 타입 프로퍼티와 연산 타입 프로퍼티가 존재하며 저장 타입 프로퍼티의 경우 선언할 당시 항상 초기화가 되어 있어야함.

staitc을 이용해 선언하며 자동으로 lazy로 작동함.

class Human {
    static let name: String = "sodeul"     // 저장 타입 프로퍼티
    static var alias: String {             // 연산 타입 프로퍼티
        return name + "은 바보"
    }
}

이런 형태를 가짐

타입 프로퍼티는 인스턴스가 생성될 때마다 생성되는게 아님.

타입 프로퍼티는 처음 호출했을때 한번 메모리에 올라가고 이후로는 처음에 생성된 프로퍼티를 공유하는 방식.

그러므로 인스턴스생성할 때 나오는 initailzaer와는 상관없음

그래서 초기값이 없으면 초기값을 정할 방법이 없기 때문에 초기값을 꼭 가져야하는것.

타입 프로퍼티에 접근하는 방법은

class Human {
    static var name = "Sodeul"
    static let age = 100
}
 
Human.name                  // "Sodeul"
Human.name = "Unknown"
Human.name                  // "Unknown"
 
Human.age = 200             // error!! 상수 변경 불가

이렇게 할 수 있고 var로 선언된 타입 프로퍼티는 수정도 가능함.

lazy 프로퍼티는 항상 var로 선언해야 했는데 얘는 ????

타입 프로퍼티는 인스턴스 프로퍼티처럼 초기화 구문의 영향을 받지않음. 인스턴스가 init함수가 불리든 말든 타입 프로퍼티와는 상관이 없는것. 그러므로 let으로 선언해도 문제가 없는것

타입 프로퍼티의 용도?

모든 타입이 공통적인 값을 정의하는데 유옹하게 쓰임

가장 대표적인 것이 싱글톤 패턴!

 

출처: https://docs.swift.org/swift-book/LanguageGuide/Properties.html

'Swift' 카테고리의 다른 글

Swift) , vs && // 컴마와 앤퍼센트 두개의 차이는?  (0) 2022.08.23
Swift) self vs Self  (0) 2022.08.11
Swift) About Enumerations  (0) 2022.08.10
Swift) About closures  (0) 2022.08.10
Swift) About Function  (0) 2022.08.10
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함