Toy Project/Swift Language Syntax

11. Swift Property(속성)

개발자킹콩 2021. 1. 21. 16:46

Property: 속성, 데이터를 의미
Stored Property: 값이 초기화되어 저장되어있는 데이터(nil로 저장된것도 포함)
Computed Property: 어떤 값을 저장하지 않고 저장된 정보를 이용해서 가공 혹은 계산된 값을 이용
접근할때마다 다시 계산이 되어 값 변경시 새로운 값을 이용해서 다시 제공한다.
Protocol에서의 예시인 var description이 Computed Property이다.

꿀팁을 주자면 변수가 var로 되어있는데 값변경으로인한 오류를 막기위해 let으로 선언을 권고

struct Person {
  var firstName: String
  var lastName: String

  var fullName: String {
    return "\(firstName) \(lastName)"
  }
}

var person = Person(firstName: "Jason", lastName: "Lee")
print(person.firstName, person.lastName)
print(person.fullName)

여기서 fullName는 Computed Property에 해당하기에 fullName를 직접 할당하거나 
업데이트 및 삭제를 할 수 없다.
fullName는 firstName, lastName 서로간의 관계가 있잖아.
이 관계만 잘 정리를 해주면 setting도 가능하게 할 수 있다. --> get, set


property의 값을 셋팅하게 되면 set이 실행되는 구조야~
새로운 값이 들어오면 newValue가 할당이 된다. newValue == "안 녕"
그럼 이 String를 구분을 지을 수 있는데 separatedBy: " " 는 공백으로 String를 구분짓는다는 의미이다.
그럼 앞의 요소와 뒤의요소가 있을 것이고,
그 요소에 대하여 firstName와 lastName을 현재받은 String로 업데이트 시키는 구조이다.




우리가 계속 변경하는 property는 instance property인데 person이라는 객체를 생성한 다음 만들수있다
이것과 별개로 type property라고 해서 
생성된 instance와 상관없이 Structure, class의 type자체를 정하고 싶을 때 사용할 수 있는 녀석이다.
Person


struct Person {
  var firstName: String
  var lastName: String

  var fullName: String {
    get {
      return "\(firstName) \(lastName)" 
    }
    set {
      // 값이 새로 새팅될때 -> newValue
      if let firstName = newValue.components(separatedBy: " ").first {
        self.firstName = firstName
      }
      if let lastName = newValue.components(separatedBy: " ").last {
        self.lastName = lastName
      }
    }
  }
  static let isAlien: Bool = false
}

var person = Person(firstName: "Jason", lastName: "Lee")

print(person.firstName, person.lastName)
print(person.fullName)

// set을 이용하기
person.fullName = "안 녕"
print(person.fullName)

// type property
print(Person.isAlien)





변수가 개명을 하게되면 서로 당황스러우니 바뀌는 시점을 알수있도록하자.
stored property에 중괄호를 열어 didSet으로 확인할 수 있다.
didSet의 경우 Stored Property에서만 사용할 수 있다.
바뀌면 전 값이 있고 현재의 값이 있는데, 현재의 값은 현재의 변수 안에 존재하고, 전 값은 oldValue다.
이렇게 stored property의 값이 변경되면 didSet이 호출되고, 여기서는 print()가 호출된다.
struct Person {
  var firstName: String {
    didSet{
      print("\(oldValue) --> \(firstName)")
    }
  }


여기서 didSet은 값이 바뀌고 나서 호출되는 것이고, 값이 바뀌기 직전에 호출시키는 방법도 존재한다.
바로 willSet이다. willSet은 값이 바뀌기 직전에 호출되는 함수이고,
현재의 값은 바뀌기 전의 값이고, 새로운 값은 newValue이다.
struct Person {
  var firstName: String {
    willSet{
      print("willSet: \(firstName) --> \(newValue)")
    }
    didSet{
      print("didSet: \(oldValue) --> \(firstName)")
    }
  }



추가로 알아볼것 : 
레이지프로퍼티(lazy property): 
인스턴스가 생성될 때 실행되는 것이 아니라, 해당 property가 접근될 때 호출되는 함수이다.
structure를 생성하게 되면 stored property의 경우 코드가 다 실행이 된다.(값 셋팅이 되어야하니깐)
이때 말고 조금 느리게 필요에 따라 접근하게 되면, 그제서야 코드가 실행되는 property가 있다.
접근 전에는 할당이 되지 않는다는 의미인가?
lazy property의 경우 lazy키워드를 쓰고 코드블럭과 ( )를 이용한다.

lazy var isPopular: Bool = {
    if fullName == "Jay Park" {
      return true
    } else {
      return false
    }
  }()

접근전에는 isPopular은 값이 정해지지 않았지만, 접근하는 순간 값이 지정된다.
이것을 왜 쓰는가??
엔지니어 측면에서 최적화를 위해 사용한다.
initial value를 생성할 때, cost가 큰 것들이 존재하기도 한다. 
그래서 초기에 설정하지 않고 실제 사용자가 접근을 할 때 사용하도록 하기 위함이다.
혹은 모든 사용자가 접근하지도 않는, 사용자 측면에서 비중이 적은 것은 lazy property로 사용하기도 함


















'Toy Project > Swift Language Syntax' 카테고리의 다른 글

13. Swift Method extension  (0) 2021.01.22
12. Swift Method  (0) 2021.01.22
10. Swift Protocol  (0) 2021.01.21
9. Swift Structure practice  (0) 2021.01.21
8. Swift Structure  (0) 2021.01.21