-
Computed Property๋ enum์์๋ ๊ฐ๋ฅํ๋ค.
-
Stored Property๋ class์ structure์์๋ง ๊ฐ๋ฅํ๋ค
-
์ธ์คํด์ค์ ํ๋กํผํฐ ์ด์ธ์๋ ํ์ ์์ฐจ์ ๋ํ ํ๋กํผํฐ๋ฅผ ๋ง๋ค ์ ์๋๋ฐ(static) ์ด๋ฅผ Type Property๋ผ๊ณ ํ๋ค.
- ํด๋์ค๋ ์คํธ๋ญ์ฒ์ ์ธ์คํด์ค์ ๊ฐ์ ์ ์ฅํ๋ ๋ฐฉ์
- var, let ์ฌ์ฉ๊ฐ๋ฅ
- ์คํธ๋ญ์ฒ์ ์ธ์คํด์ค๋ฅผ let์ผ๋ก ์ ์ฅํ๋ฉด ์คํธ๋ญ์ฒ ๋ด๋ถ์ ๊ฐ์ ๋ฐ๊ฟ์ ์๋ค.(var๋ก ์ ์ธํ์๋ค ํ๋๋ผ๋)
- ์๋ ์์
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
// this range represents integer values 0, 1, 2, and 3
rangeOfFourItems.firstValue = 6
// this will report an error, even though firstValue is a variable property
-
๊ทธ ์ด์ ๋ ์คํธ๋ญ์ฒ์ value type์ด๊ธฐ ๋๋ฌธ์. ์ธ์คํด์ค๊ฐ ์์ํ๋์ด์ ๋ด๋ถ์ ํ๋กํผํฐ ๋ง์ ์์ํ๋์ด๋ฒ๋ฆผ
-
ํ์ง๋ง ํด๋์ค๋ reference type์ด๊ธฐ ๋๋ฌธ์ ๋ค๋ฅด๋ค. ์ธ์คํด์ค๊ฐ ์์๋ก ์ ์ธ๋์ด๋ ๋ด๋ถ์ var๋ก ์ ์ธ๋ stored property๋ค์ ๋ณ๊ฒฝ๊ฐ๋ฅํ๋ค.
- lazy Stored property๋ ๊ฐ์ด ์ฌ์ฉ๋๊ธฐ ์ ๊น์ง ์ด๊ธฐ๊ฐ์ด ์ฐ์ฐ๋์ง ์๋๋ค.
NOTE lazy property๋ ๋ณ์๋ง ๊ฐ๋ฅํ๋ค.(์์ ๋ถ๊ฐ๋ฅ) ์์๋ ์ธ์คํด์ค์ ์ด๊ธฐํ๊ฐ ๋๋๊ธฐ ์ ์ ๊ฐ์ ๊ฐ๊ณ ์์ด์ผ ํ๋๋ฐ lazy property๋ ์ด๊ธฐํ๊ฐ ๋๋๋ ๊ฐ์ด ์๊ธฐ๋๋ฌธ์ ๋ณ์๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
- lazy Stored property๋ 2๊ฐ์ง ์ฉ๋๋ก ๋ง์ด ์ฐ์ด๋๋ฐ
- property์ ์ด๊ธฐ๊ฐ์ด ์ธ๋ถ์ ๊ฐ์ผ๋ก ๋ถํฐ ์ ํด์ง๋ ๊ฒฝ์ฐ
- property์ ๊ฐ์ ๊ตฌํ ๋ ์ฐ์ฐ์ด ๋ง์ด ๊ฑธ๋ฆฌ๋ ๊ฒฝ์ฐ
์๋ ์ฝ๋์ ๊ฒฝ์ฐ DataImporter์์ ํ์ผ์ ๋ถ๋ฌ์ค๋ ์ฝ๋๋ฅผ ์์ฑํ๋ค๊ณ ๊ฐ์ ํ์๋ ๊ฝค๋ง์ ์๊ฐ์ด ์์๋๋ค. DataManager๊ฐ ๋จ์ํ data array์ ๋ฐ์ดํฐ๋ง ์ถ๊ฐํ๋ค๊ณ ํ๋ฉด importer๊ฐ ํ์์์ ์ ์๋ค. ๋ฐ๋ผ์ lazy keyword๋ฅผ ํตํด ๋ค์๊ณผ ๊ฐ์ด importer๊ฐ ์ง์ง ํ์ํ ์์ ์ ์์ฑ๋๋๋ก ํ ์ ์๋ค.
class DataImporter {
/*
DataImporter is a class to import data from an external file.
The class is assumed to take a nontrivial amount of time to initialize.
*/
var filename = "data.txt"
// the DataImporter class would provide data importing functionality here
}
class DataManager {
lazy var importer = DataImporter()
var data: [String] = []
// the DataManager class would provide data management functionality here
}
let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
// the DataImporter instance for the importer property hasn't yet been created
์๋ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ ๊น์ง importer๋ ์ด๊ธฐํ ๋์ง ์๋๋ค.
print(manager.importer.filename)
// the DataImporter instance for the importer property has now been created
// Prints "data.txt"
NOTE ๋ง์ฝ lazy stored property๊ฐ ์ฌ๋ฌ๊ฐ์ ์ฐ๋ ๋์ ์ํด ๋์์ ์ ๊ทผ๋๋ค๋ฉด, ๋ฑํ๋ฒ๋ง ์ด๊ธฐํ๋๋ค๋ ๋ณด์ฅ์ ์๋ค
If you have experience with Objective-C, you may know that it provides two ways to store values and references as part of a class instance. In addition to properties, you can use instance variables as a backing store for the values stored in a property.
Swift unifies these concepts into a single property declaration. A Swift property doesnโt have a corresponding instance variable, and the backing store for a property isnโt accessed directly. This approach avoids confusion about how the value is accessed in different contexts and simplifies the propertyโs declaration into a single, definitive statement. All information about the propertyโincluding its name, type, and memory management characteristicsโis defined in a single location as part of the typeโs definition.
- Enumeration์๋ Stored property๊ฐ ์์ง๋ง Computed property๋ ๊ฐ์ง ์ ์๋ค. ๋ค๋ง ๊ฐ์ ์ ์ฅํ ์๋ ์๋ค.
struct Point {
var x = 0.0, y = 0.0
}
struct Size {
var width = 0.0, height = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set(newCenter) {
origin.x = newCenter.x - (size.width / 2)
origin.y = newCenter.y - (size.height / 2)
}
}
}
var square = Rect(origin: Point(x: 0.0, y: 0.0),
size: Size(width: 10.0, height: 10.0))
let initialSquareCenter = square.center
// initialSquareCenter is at (5.0, 5.0)
square.center = Point(x: 15.0, y: 15.0)
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
// Prints "square.origin is now at (10.0, 10.0)"
- setter์ ๊ตณ์ด newCenter๋ฅผ ๋ช ์ ์ํด๋ newValue๋ก ์ ๊ทผํด์ set ์๊ธฐ์ ๋ฐ์ ์ธ์๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
- ์๋ ์ฝ๋๋ ์์ ๊ฐ์ ๋์์ ํ๋ค.
struct AlternativeRect {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set {
origin.x = newValue.x - (size.width / 2)
origin.y = newValue.y - (size.height / 2)
}
}
}
- getter๊ฐ ํ์ค๋ก๋ง ์ด๋ฃจ์ด์ ธ ์๋ค๋ฉด(single expression) ๊ตณ์ด return์ ์์ ์ด๋ return ๋๋ค.
- ์์ ๋ฃฐ์ function์์๋ ๊ทธ๋๋ก ์๋ํ๋ค(Implicit Return)
- ์๋ ์ฝ๋๋ ์์ ๊ฐ์ ๋์์ ํ๋ค.
struct CompactRect {
var origin = Point()
var size = Size()
var center: Point {
get {
Point(x: origin.x + (size.width / 2),
y: origin.y + (size.height / 2))
}
set {
origin.x = newValue.x - (size.width / 2)
origin.y = newValue.y - (size.height / 2)
}
}
}
- computed property์ getter๋ง ์๊ณ setter๊ฐ ์๋ค๋ฉด ์ฝ๊ธฐ ์ ์ฉ computed property๋ผ๊ณ ํ๋ค.
- ํํ๋ง์ผ๋ก ์ ์ ์์ง๋ง ์ฝ๊ธฐ๋ง ๋๊ณ set์ด ๋์ง ์๋๋ค.
NOTE Computed property๋(read-only computed propertyํฌํจ) ํญ์ var๋ก ์ ์ธ๋์ด์ผ ํ๋ค. ์๋ํ๋ฉด ๊ณ ์ ๋ ๊ฐ์ด ์๋๊ธฐ ๋๋ฌธ์ด๋ค. ์์๋ ์ธ์คํด์ค ์ด๊ธฐํํ์ ํ ๋น๋ ๊ฐ์ด ๋ณํ๋ฉด ์๋๊ธฐ ๋๋ฌธ์ด๋ค.
(You must declare computed propertiesโincluding read-only computed propertiesโas variable properties with the var keyword, because their value isnโt fixed. The let keyword is only used for constant properties, to indicate that their values canโt be changed once theyโre set as part of instance initialization.)
- read-only computed property๋ get์ ์๋ตํ๊ณ ์ธ ์ ์๋ค.
struct Cuboid {
var width = 0.0, height = 0.0, depth = 0.0
var volume: Double {
return width * height * depth
}
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
// Prints "the volume of fourByFiveByTwo is 40.0"
- ํ๋กํผํฐ์ ๋ณํ๋ฅผ ๊ฐ์ํ๋ ๋ฌธ๋ฒ
- ํ๋กํผํฐ์ property observer๋ฅผ ๋ฌ๋ฉด ํ๋กํผํฐ์ ์๋ก์ด ๊ฐ์ด ํ ๋น๋ ๋๋ง๋ค property observer๊ฐ ์คํ๋๋ค.
- ํ์ฌ ๊ฐ๊ณผ ๊ฐ์ ๊ฐ์ ํ ๋นํด๋ property observer๊ฐ ์คํ๋๋ค.
ํ๋กํผํฐ ์ต์ ๋ฒ๋ฅผ ์ถ๊ฐํ ์ ์๋ ๊ณณ์ ๋ค์๊ณผ ๊ฐ๋ค:
-
Stored properties that you define
-
Stored properties that you inherit
-
Computed properties that you inherit
-
์์๋ ํ๋กํผํฐ์ ํ๋กํผํฐ ์ต์ ๋ฒ๋ฅผ ์ถ๊ฐํ๊ธฐ ์ํด์๋ property๋ฅผ overrideํด์ ์ถ๊ฐํด์ผ ํ๋ค.
-
์์ 3๊ณณ์ค์ ์ธ๊ธ์ด ๋์ง ์์ ์ง์ ์ ์ํ computed property์ ๊ฒฝ์ฐ setter๊ฐ property observer์ ์ญํ ์ ๋์ ํ ์ ์๋ค.
ํ๋กํผํฐ ์ต์ ๋ฒ๋ ์๋ ํ๊ธฐ๋๊ฒ์ฒ๋ผ 2๊ฐ์ง๊ฐ ์๋ค:
-
willSet: ๊ฐ์ด ์ ์ฅ๋๊ธฐ ์ง์ ์ ์คํ๋๋ค.
-
didSet: ๊ฐ์ด ์ ์ฅ๋์๋ง์ ์คํ๋๋ค.
-
willSet ์ต์ ๋ฒ๋ฅผ ๊ตฌํํ๋ฉด ์๋ก ํ ๋น๋ ๊ฐ์ด ์์ ์ธ์๋ก ๋์ด์ค๊ฒ ๋๋ค. ์ด ์ธ์์ ์ด๋ฆ์ ์๋ก ์ง์ ํ ์๋ ์๊ณ newValue๋ผ๋ ํ๋ผ๋ฏธํฐ ์ด๋ฆ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
-
didSet๋ ๋ง์ฐฌ๊ฐ์ง๋ก ์๋ ์ง์ ๋์๋ ๊ฐ์ด ์์ ์ธ์๋ก ๋์ด์ค๊ฒ ๋๋ค. ์ธ์์ ์ด๋ฆ์ ์ง์ ํ์ง ์์ผ๋ฉด oldValude๋ก ์ฌ์ฉํ ์ ์๋ค.
NOTE The willSet and didSet observers of superclass properties are called when a property is set in a subclass initializer, after the superclass initializer has been called. They arenโt called while a class is setting its own properties, before the superclass initializer has been called.
For more information about initializer delegation, see Initializer Delegation for Value Types and Initializer Delegation for Class Types.
willSet, didSet ์์
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
stepCounter.totalSteps = 896
// About to set totalSteps to 896
// Added 536 steps
NOTE ํ๋กํผํฐ ์ต์ ๋ฒ๊ฐ ๋ฌ๋ฆฐ ํ๋กํผํฐ๋ฅผ ํจ์์ in-out parameter๋ก ๋ฃ๋๋ค๋ฉด willSet๊ณผ didSet์ด ํญ์ ํธ์ถ๋๋ค. in-out parameter๋ copy-in, copy-out ๋ฉ๋ชจ๋ฆฌ ๋ชจ๋ธ๋๋ฌธ์ธ๋ฐ ํจ์๊ฐ ์ข ๋ฃ๋ ๋ ์ธ์๋ก ๋์ด์จ ํ๋กํผํฐ๋ฅผ ํญ์ ๋ฎ์ด์ฐ๊ธฐ ๋๋ฌธ์ด๋ค.
ํ๋กํผํฐ๋ง๋ค ๋์ผํ ๋์์ ํด์ผํ ๋ ํ๋กํผํฐ ๋ํผ๋ฅผ ์ฌ์ฉํ๋ฉด ํธํ๋ค
ํ๋กํผํฐ ๋ํผ๋ฅผ ๋ง๋๋ ค๋ฉด ๊ตฌ์กฐ์ฒด, enum, class์ wrappedValue ํ๋กํผํฐ๋ฅผ ๋ง๋ค์ด์ฃผ๋ฉด ๋๋ค.
@propertyWrapper
struct TwelveOrLess {
private var number = 0
var wrappedValue: Int {
get { return number }
set { number = min(newValue, 12) }
}
}
NOTE ์์ ์ฝ๋์์ number์ ๊ฒฝ์ฐ wrappedValue๋ฅผ ํตํด์๋ง ์ ๊ทผํ ์ ์๊ฒ private์ผ๋ก ์ ์ธ๋์ด ์๋๊ฒ์ ์ฃผ์!
struct SmallRectangle {
@TwelveOrLess var height: Int
@TwelveOrLess var width: Int
}
var rectangle = SmallRectangle()
print(rectangle.height)
// Prints "0"
rectangle.height = 10
print(rectangle.height)
// Prints "10"
rectangle.height = 24
print(rectangle.height)
// Prints "12"
height ์ width ํ๋กํผํฐ๋ ์์ TwelveOrLess์์ ์ ์๋ ๋๋ก ์ด๊ธฐ๊ฐ 0์ ๊ฐ๋๋ค. height์ 10์ ๋ฃ์ผ๋ฉด 10์ด ์ ์ฅ๋๊ณ height์ 24๋ฅผ ํ ๋นํ๋ฉด min(newValue, 12)
์ ์ํด 12๊ฐ ํ ๋น๋๋ค.
ํ๋กํผํฐ ๋ํผ๋ @
์ ํตํด ๋ฌธ๋ฒ์ ๊ฐํธํจ์ ์ ๊ณตํ๋๋ฐ ๋ง์ฝ ์ด ๊ธฐํธ๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ง ์๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํ ์๋ ์๋ค.
struct SmallRectangle {
private var _height = TwelveOrLess()
private var _width = TwelveOrLess()
var height: Int {
get { return _height.wrappedValue }
set { _height.wrappedValue = newValue }
}
var width: Int {
get { return _width.wrappedValue }
set { _width.wrappedValue = newValue }
}
}
์์์๋ ํ๋กํผํฐ๋ํผ๋ฅผ ์ ์ฉํ ํ๋กํผํฐ์ ์ด๊ธฐ๊ฐ์ 0์ผ๋ก ๊ณ ์ ๋์์๋ค. ์ฌ๊ธฐ์ ์ฌ๋ฌ๊ฐ์ง ์ด๊ธฐ๊ฐ์ ์ฃผ๊ธฐ์ํด ํ๋กํผํฐ ๋ํผ์ ์์ฑ์๋ฅผ ์ถ๊ฐํ ์ ์๋ค.
@propertyWrapper
struct SmallNumber {
private var maximum: Int
private var number: Int
var wrappedValue: Int {
get { return number }
set { number = min(newValue, maximum) }
}
init() {
maximum = 12
number = 0
}
init(wrappedValue: Int) {
maximum = 12
number = min(wrappedValue, maximum)
}
init(wrappedValue: Int, maximum: Int) {
self.maximum = maximum
number = min(wrappedValue, maximum)
}
}
์ฒซ๋ฒ์ฌ ์์ฑ์ ์ฌ์ฉ(์ด๊ธฐ๊ฐ์ ์ง์ ์ ํด์ฃผ์ง ์์)
struct ZeroRectangle {
@SmallNumber var height: Int
@SmallNumber var width: Int
}
var zeroRectangle = ZeroRectangle()
print(zeroRectangle.height, zeroRectangle.width)
// Prints "0 0"
๋๋ฒ์งธ ์์ฑ์ ์ฌ์ฉ ํ๋กํผํฐ ๋ํผ๋ฅผ ์ ์ฉํ ํ๋กํผํฐ์ ์ด๊น๊ฐ์ ์ ํด์ฃผ๋ฉด ์๋์ผ๋ก init(wrappedValue: Int)๊ฐ ์คํ๋๊ณ ์ง์ ๋ ์ด๊ธฐ๊ฐ์ด ์ธ์๋ก ๋ค์ด๊ฐ๋ค.
struct UnitRectangle {
@SmallNumber var height: Int = 1
@SmallNumber var width: Int = 1
}
var unitRectangle = UnitRectangle()
print(unitRectangle.height, unitRectangle.width)
// Prints "1 1"
์ธ๋ฒ์งธ ์์ฑ์ ์ฌ์ฉ ๋ง์ฝ wrappedValue์ด์ธ์ ์ธ์๋ฅผ ๋ฃ์ด์ฃผ๊ณ ์ถ์ผ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
struct NarrowRectangle {
@SmallNumber(wrappedValue: 2, maximum: 5) var height: Int
@SmallNumber(wrappedValue: 3, maximum: 4) var width: Int
}
var narrowRectangle = NarrowRectangle()
print(narrowRectangle.height, narrowRectangle.width)
// Prints "2 3"
narrowRectangle.height = 100
narrowRectangle.width = 100
print(narrowRectangle.height, narrowRectangle.width)
// Prints "5 4"
height์ width๋ ๋ค๋ฅธ ์ธ์คํด์ค์ด๋ค. ๊ฐ ์ธ์คํด์ค๋ง๋ค ๋ค๋ฅธ ์ด๊ธฐ ์ค์ ์ ์ค ์ ์๋ค. ์ด 3๋ฒ์งธ ๋ฐฉ์์ด ๊ฐ์ฅ ๋๋ฆฌ์ฐ๋ ๋ฐฉ์์ด๋ค.
๋ค๋ฅธ ์ธ์๊ฐ ์๋๋ผ๋ wrappedValue๋ ์ด๊ธฐ๊ฐ์ ์ง์ ํด์ฃผ๋ ๋ฐฉ์์ผ๋ก ์ธ์๋ฅผ ๋๊ฒจ์ค ์ ์๋ค. <- ์ด๊ฑฐ ํฌํํ๋ค ์๋ height์ width๋ฅผ ๋ณด๋ฉด ๋๋ค.
struct MixedRectangle {
@SmallNumber var height: Int = 1
@SmallNumber(maximum: 9) var width: Int = 2
}
var mixedRectangle = MixedRectangle()
print(mixedRectangle.height)
// Prints "1"
mixedRectangle.height = 20
print(mixedRectangle.height)
// Prints "12"
Property wrapper์ projected value๋ผ๋ ์ถ๊ฐ ๊ธฐ๋ฅ์ด ์๋ค. $ํ์๋ฅผ ์ด์ฉํด์ ์ถ๊ฐ์ ์ธ ๊ฐ์ ์ ์ฅํ ์ ์๋ค. ์ด๋ ์ด๋ฆ์ projectedValue๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
@propertyWrapper
struct SmallNumber {
private var number: Int
private(set) var projectedValue: Bool
var wrappedValue: Int {
get { return number }
set {
if newValue > 12 {
number = 12
projectedValue = true
} else {
number = newValue
projectedValue = false
}
}
}
init() {
self.number = 0
self.projectedValue = false
}
}
struct SomeStructure {
@SmallNumber var someNumber: Int
}
var someStructure = SomeStructure()
someStructure.someNumber = 4
print(someStructure.$someNumber)
// Prints "false"
someStructure.someNumber = 55
print(someStructure.$someNumber)
// Prints "true"
projectedValue์ ์ด๋ค ํ์ ๋ ์ ์ฅํ ์ ์๋ค. ์ฌ๊ธฐ์์๋ boolํ์ ๋ง์ ๋ฆฌํดํ๋๋ฐ ๋ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ๋ฆฌํดํ๊ณ ์ถ๋ค๋ฉด costume type์ ๋ง๋ค๋ฉด ๋๋ค.
๋ฐ์ ์ฒ๋ผ projectedNumber์ @height, @width๋ก ์ ๊ทผํ ์ ์๋ค. ์ด๋ self๋ ์๋ต๊ฐ๋ฅํ๋ค.
enum Size {
case small, large
}
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
}
}
stored property์ computed property๋ชจ๋ global, local scope์์ ์ฌ์ฉํ ์ ์๋ค. ์ด๋๋ ํ์ ์ property๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ๋ช ์นญ์ stoed variable, compputed variable์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
NOTE global ๋ณ์๋ ์์๋ lazyํค์๋๊ฐ ์์ด๋ ํญ์ lazyํ๊ฒ ์๋ํใทk. local ๋ณ์์ ์์๋ lazyํ๊ฒ ์๋ํ ์ ์๋ค.(lazyํค์๋ ๋ถ์ด๋ฉด ์๋ฌ๊ฐ ๋๋ค.)
์๋ ์์์ฒ๋ผ local scope์์๋ property wrapper๋ฅผ ์ฌ์ฉํ ์ ์๋ค.(global scope์์๋ ๋ถ๊ฐ๋ฅ)
func someFunction() {
@SmallNumber var myNumber: Int = 0
myNumber = 10
// now myNumber is 10
myNumber = 24
// now myNumber is 12
}
์ธ์คํด์ค์ ์ข ์๋์ง ์์ type property๋ฅผ ๋ง๋ค ์ ์๋ค. ์ด๋ stored type property๋ lazyํ๊ฒ ์๋๋๋ฉด ๋์์ ์ฌ๋ฌ ์ฐ๋ ๋๊ฐ ์ ๊ทผํ๋ค ํ๋๋ผ๋ ๋ฑ ํ๋ฒ๋ง ์ด๊ธฐํ ๋๋๊ฒ ๋ณด์ฅ๋๋ค. ๋ํ stored type property๋ initializer๊ฐ ์๊ธฐ๋๋ฌธ์ ํญ์ ์ด๊ธฐ๊ฐ์ ๊ฐ๊ณ ์์ด์ผ ํ๋ค.
type property๋ฅผ ๋ง๋๋ ๊ฒฝ์ฐ static ํค์๋๋ฅผ ์ฌ์ฉํ๋ค. ๋ค๋ง ํด๋์ค์ computed ํ๋กํผํฐ์ ๊ฒฝ์ฐ subclass๊ฐ override๋ฅผ ํ์ฉํ๋ ค๋ฉด classํค์๋๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค. ์๋๋ ์์ class์ computed type property๋ฅผ ๋ง๋๋ ๊ฒฝ์ฐ class ํค์๋๋ฅผ ์ฌ์ฉํด์ผํ๋ค. (๊ทธ ์ธ์๋ ์ ๋ถ static ํค์๋๋ฅผ ์ฌ์ฉํ๋ค.)
struct SomeStructure {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 1
}
}
enum SomeEnumeration {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 6
}
}
class SomeClass {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 27
}
class var overrideableComputedTypeProperty: Int {
return 107
}
}
NOTE ์์ ์์ ๋ ๋ชจ๋ read-only์ธ๋ฐ read-write๋ ๊ฐ์ ๋ฌธ๋ฒ์ผ๋ก ์์ฑ๊ฐ๋ฅํจ.
ํ์ ํ๋กํผํฐ์๋ ๊ฐ์ ์ ์ฅํ ์ ์๋ค. ์ด๋ instance๊ฐ ์๋ type์ ์ ์ฅ๋๋๊ฒ์ ์ฃผ์ํด์ผ ํใทใ .
print(SomeStructure.storedTypeProperty)
// Prints "Some value."
SomeStructure.storedTypeProperty = "Another value."
print(SomeStructure.storedTypeProperty)
// Prints "Another value."
print(SomeEnumeration.computedTypeProperty)
// Prints "6"
print(SomeClass.computedTypeProperty)
// Prints "27"