๊ฐ„๋‹จํ•˜๊ฒŒ property๋Š” member ๋ณ€์ˆ˜์ด๋‹ค. ๊ทธ๋Ÿฐ๋ฐ Swift์—๋Š” ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ property๊ฐ€ ์กด์žฌํ•œ๋‹ค. ์‚ฌ์‹ค ์–ด๋–ป๊ฒŒ ๋ณด๋ฉด ํ™œ์šฉ๋ฐฉ๋ฒ•? ํ…Œํฌ๋‹‰์— ๊ฐ€๊น๊ฒ ๋‹ค. ์–ด๋–ป๊ฒŒ property๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ง€ ์•ˆ๋‹ค๋ฉด, ์‹ค์ œ ์ฝ”๋“œ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ณ  ์ฝ๊ธฐ ์ข‹๊ฒŒ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿผ ์ถœ๋ฐœํ•ด๋ณด์ž.

Property์˜ ์ข…๋ฅ˜

  • ์—ญํ• ์— ๋”ฐ๋ฅธ ๋ถ„๋ฅ˜
    • ์ธ์Šคํ„ด์Šค ํ”„๋กœํผํ‹ฐ
    • ํƒ€์ž… ํ”„๋กœํผํ‹ฐ
  • ์ข…๋ฅ˜
    • ์ €์žฅ ํ”„๋กœํผํ‹ฐ
    • ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ
      • var๋กœ๋งŒ ์„ ์–ธ ๊ฐ€๋Šฅ
      • ์ฝ๊ธฐ ์ „์šฉ ๊ตฌํ˜„์€ ๊ฐ€๋Šฅ - get ๋ธ”๋ก์„ ์ž‘์„ฑ
      • ์“ฐ๊ธฐ ์ „์šฉ ๊ตฌํ˜„์€ ๋ถˆ๊ฐ€๋Šฅ

์œ„์˜ 4๊ฐ€์ง€๊ฐ€ ์„ž์—ฌ์„œ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰ 4๊ฐ€์ง€์˜ ๊ฐ€๋Šฅ์„ฑ์ด ์กด์žฌ.

  • ์ธ์Šคํ„ด์Šค ์ €์žฅ ํ”„๋กœํผํ‹ฐ
  • ํƒ€์ž… ์ €์žฅ ํ”„๋กœํผํ‹ฐ
  • ์ธ์Šคํ„ด์Šค ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ
  • ํƒ€์ž… ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ

Property์˜ ํŠน์ง•

  • ๊ตฌ์กฐ์ฒด, ํด๋ž˜์Šค, ์—ด๊ฑฐํ˜• ๋‚ด๋ถ€์— ๊ตฌํ˜„์ด ๊ฐ€๋Šฅ
  • ์—ด๊ฑฐํ˜•์—๋Š” ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ๋งŒ ๊ตฌํ˜„ ๊ฐ€๋Šฅ
  • ์ฝ๊ธฐ ์“ฐ๊ธฐ ๋ชจ๋‘๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋ ค๋ฉด get ๋ธ”๋Ÿญ๊ณผ set ๋ธ”๋Ÿญ ๋ชจ๋‘ ๊ตฌํ˜„
    • ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ๋งŒ๋“ค๊ณ  ์‹ถ์œผ๋ฉด get๋งŒ ๊ตฌํ˜„
  • set์—์„œ ์•”์‹œ์  ๋งค๊ฐœ๋ณ€์ˆ˜ newValue๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
struct Student {
    // ์ธ์Šคํ„ด์Šค ์ €์žฅ ํ”„๋กœํผํ‹ฐ
    var name: String = ""
    var `class`: String = "Swift"
    var koreanAge: Int = 0
    
    // ์ธ์Šคํ„ด์Šค ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ
    var westernAge: Int {
        get {
            return koreanAge - 1
        }
        set(inputValue) {
            koreanAge = inputValue + 1
        }
    }
    
    // ํƒ€์ž… ์ €์žฅ ํ”„๋กœํผํ‹ฐ
    static var typeDescription: String = "ํ•™์ƒ"
    
    // ์ฝ๊ธฐ ์ „์šฉ ํƒ€์ž… ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ
    // ์ฝ๊ธฐ ์ „์šฉ์ด default๋ผ ์ ์ง€ ์•Š์œผ๋ฉด ์ฝ๊ธฐ์ „์šฉ์ด๋ผ๊ณ  ํŒ๋‹จํ•จ
    static var selfintroduction: String {
        return "ํ•™์ƒํƒ€์ž…์ž…๋‹ˆ๋‹ค."
    }
}
  • ์ธ์Šคํ„ด์Šค ์ €์žฅ ํ”„๋กœํผํ‹ฐ๋Š” ์ผ๋ฐ˜์ ์ด๋‹ˆ ํŒจ์Šค
  • ์ธ์Šคํ„ด์Šค ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ๋Š”, ํŠน์ •๊ฐ’์„ ๋ฐ›์•„์„œ ๋‹ค๋ฅธ ์ €์žฅ ์ธ์Šคํ„ด์Šค์˜ ๊ฐ’์„ ์„ค์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ํ”„๋กœํผํ‹ฐ๋กœ ๋ถ€ํ„ฐ ์—ฐ์‚ฐ์„ ํ†ตํ•ด ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์ด ๋„์ถœ๋  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉ
  • ํƒ€์ž… ์ €์žฅ ํ”„๋กœํผํ‹ฐ๋Š” ๊ธฐ์กด์— ์•Œ๊ณ  ์žˆ๋˜ ํƒ€์ž… ํ”„๋กœํผํ‹ฐ
  • ํƒ€์ž… ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ ์—ญ์‹œ ๋น„์Šทํ•˜๋‹ค.
  • ์ด๋Ÿฌํ•œ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ธฐ์กด์˜ introduce์™€ ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ์ฝ๊ธฐ ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€์ฒดํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅ
// ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
var wansik: Student = Student()
wansik.name = "wansik"
wansik.koreanAge = 20
 
// ์ธ์Šคํ„ด์Šค ์ €์žฅ ํ”„๋กœํผํ‹ฐ ์‚ฌ์šฉ
print(wansik.name) // wansik
 
// ์ธ์Šคํ„ด์Šค ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ ์‚ฌ์šฉ
print(wansik.westernAge) // 19
 
// ํƒ€์ž… ์ €์žฅ ํ”„๋กœํผํ‹ฐ ์‚ฌ์šฉ
print(Student.typeDescription) // ํ•™์ƒ
 
// ํƒ€์ž… ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ ์‚ฌ์šฉ
print(Student.selfintroduction) // "ํ•™์ƒํƒ€์ž…์ž…๋‹ˆ๋‹ค."

Property Observers

  • ํ”„๋กœํผํ‹ฐ ๊ฐ์‹œ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ”„๋กœํผํ‹ฐ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ, ์›ํ•˜๋Š” ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Œ
  • ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๊ธฐ ์ง์ „์— willSet ๋ธ”๋Ÿญ์ด, ๋ณ€๊ฒฝ ์งํ›„ didSet ๋ธ”๋Ÿญ์ด ํ˜ธ์ถœ๋จ
  • ๋ณ€๊ฒฝ๋˜๋ ค๋Š” ๊ฐ’์ด ๊ธฐ์กด ๊ฐ’๊ณผ ๊ฐ™๋”๋ผ๋„ ํ•ญ์ƒ ๋™์ž‘
  • willSet ๋ธ”๋Ÿญ์—์„œ ์•”์‹œ์  ๋งค๊ฐœ๋ณ€์ˆ˜ newValue๋ฅผ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • didSet ๋ธ”๋Ÿญ์—์„œ๋Š” oldValue๋ฅผ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • ํ”„๋กœํผํ‹ฐ ๊ฐ์‹œ์ž๋Š” ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ์—์„œ ์‚ฌ์šฉ ๋ถˆ๊ฐ€
  • ํ•จ์ˆ˜, ๋ฉ”์„œ๋“œ, ํด๋กœ์ €, ํƒ€์ž… ๋“ฑ์˜ ์ง€์—ญ/์ „์—ญ ๋ณ€์ˆ˜์— ๋ชจ๋‘ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
struct Money {
    // ํ”„๋กœํผํ‹ฐ ๊ฐ์‹œ์ž ์‚ฌ์šฉ
    var currencyRate: Double = 1100 {
        willSet(newRate) {
            print("ํ™˜์œจ์ด \(currencyRate)์—์„œ \(newRate)์œผ๋กœ ๋ณ€๊ฒฝ๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค")
        }
        didSet(oldRate) {
            print("ํ™˜์œจ์ด \(oldRate)์—์„œ \(currencyRate)์œผ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค")
        }
    }
    
    // ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์•”์‹œ์ ์œผ๋กœ newValue, oldValue๋ฅผ ๊ฐ–๋Š”๋‹ค.
    var dollar: Double = 0 {
        willSet {
            print("\(dollar)๋‹ฌ๋Ÿฌ์—์„œ \(newValue)๋‹ฌ๋Ÿฌ๋กœ ๋ณ€๊ฒฝ๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค")
        }
        didSet {
            print("\(oldValue)๋‹ฌ๋Ÿฌ์—์„œ \(dollar)๋‹ฌ๋Ÿฌ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค")
        }
    }
    
    // ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ
    var won: Double {
        get {
            return dollar * currencyRate
        }
        set {
            dollar = newValue / currencyRate
        }
        // get, set๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€ํ•จ
//        willSet {
//            print("์›ํ™”์˜ ๊ฐ’์ด \(won)์œผ๋กœ ๋ณ€๊ฒฝ๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.")
//        }
//        didSet {
//            print("์›ํ™”์˜ ๊ฐ’์ด \(won)์œผ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
//        }
    }
}
 
var moneyInMyPocket = Money()
 
// ํ™˜์œจ์ด 1100.0์—์„œ 1150.0์œผ๋กœ ๋ณ€๊ฒฝ๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค
moneyInMyPocket.currencyRate = 1150.0
// ํ™˜์œจ์ด 1100.0์—์„œ 1150.0์œผ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค
 
//0.0๋‹ฌ๋Ÿฌ์—์„œ 10.0๋‹ฌ๋Ÿฌ๋กœ ๋ณ€๊ฒฝ๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค
moneyInMyPocket.won = 11500
//0.0๋‹ฌ๋Ÿฌ์—์„œ 10.0๋‹ฌ๋Ÿฌ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค
 
print(moneyInMyPocket.dollar) // 10

Property Wrappers

  • property ์ €์žฅ ๋ฐฉ๋ฒ• ์ฝ”๋“œ์™€ property ๊ด€๋ฆฌ ์ฝ”๋“œ๋ฅผ ๊ตฌ๋ถ„

  • property set, getํ•  ๋•Œ ๊ณตํ†ต์ ์œผ๋กœ ์ ์šฉ๋˜๋Š” ๋ฐ˜๋ณต์ฝ”๋“œ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ

    • ๋ฐ์ดํ„ฐ ์ €์žฅ์ „ ์Šค๋ ˆ๋“œ ์ฒดํฌ
  • struct, enum, class ์„ ์–ธ ์•ž์— @propertyWrapper๋ฅผ ๋ถ™์ด๊ณ  wrappedValue ์ •์˜ํ•˜๋ฉด ๋จ

  • ํŠน์ • ๋ฐ์ดํ„ฐ์˜ boundary๋ฅผ ์ •ํ•  ์ˆ˜ ์žˆ์Œ

    @propertyWrapper struct TwelveOrLess {
        private var number = 0
        var wrappedValue: Int {
            get { return number }
            set { number = min(newValue, 12) }
        }
    }
     
    struct SmallRectangle {
        @TwelveOrLess var height: Int
        @TwelveOrLess var width: Int
    }
  • Initializer๋ฅผ ํ†ตํ•ด value ์ดˆ๊ธฐํ™” ๊ฐ€๋Šฅ

    @propertyWrapper struct SmallNumber {
        private var maximum: Int
        private var number: Int
        
        var wrappedValue: Int {
            get { return number }
            set { number = min(newValue, maximum) }
        }
        
        init() {
            self.maximum = 12
            self.number = 0
        }
        
        init(maximum: Int) {
            self.maximum = maximum
            self.number = 0
        }
        
        init(wrappedValue: Int, maximum: Int) {
            self.maximum = maximum
            self.number = min(wrappedValue, maximum)
        }
    }
     
    struct ZeroRectangle {
        @SmallNumber(wrappedValue: 5, maximum: 10) var height: Int // custom initializer๋ฅผ ์‚ฌ์šฉํ•œ ์ดˆ๊ธฐํ™”
        @SmallNumber(maximum: 10) var width: Int = 5 // ๊ฐ’ ํ• ๋‹น๊ณผ custom initializer๋ฅผ ์„ž์–ด์„œ ์‚ฌ์šฉํ•จ
    }
  • Projected Value

    • projectValue๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด wrappedValue๋ฅผ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ ๋“œ๋Ÿฌ๋‚ผ ์ˆ˜ ์žˆ์Œ
    • $๋ฅผ ํ†ตํ•ด ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•จ
      @propertyWrapper struct SmallNumber {
          private var number = 0
          
          var projectedValue = false
          var wrappedValue: Int {
              get { return number }
              set {
                  if newValue > 12 {
                      number = 12
                      projectedValue = true
                  } else {
                      number = newValue
                      projectedValue = false
                  }
              }
          }
      }
       
      struct SizedRectangle {
          @SmallNumber var height: Int
          @SmallNumber var width: Int
          
          mutating func resize(to size: Size) -> Bool {
              switch size {
                  case .small:
                      height = 10
                      width = 20
                  case .large:
                      height = 100
                      width = 100
              }
              return $height || $width // True or False || True or False
          }
      }