var, let 키워드로 변수나 상수 값을 저장할 수 있는 프로퍼티를 stored property라고 한다.
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
rangeOfThreeItems.firstValue = 6
rangeOfThreeItems.length = 5 // error, length is let
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
rangeOfFourItems.firstValue = 6 // error, rangeOfFourItems is let
상수에 저장한 구조체 인스턴스는 생성 이후 프로퍼티 값을 변경할 수 없다.
이는 구조체가 value type이기 때문이고, reference type인 class와 다른 부분이다.
The same is not true for classes, which are reference types. If you assign an instance of a reference type to a constant, you can still change that instance’s variable properties.
class FixedLengthRange {
var firstValue: Int = 0
let length: Int = 3
}
var rangeOfThreeItems = FixedLengthRange()
rangeOfThreeItems.firstValue = 6
rangeOfThreeItems.length = 4 //error, lenth is let
let rangeOfThreeItems = FixedLengthRange()
rangeOfThreeItems.firstValue = 6 // it's ok
rangeOfThreeItems.length = 4 //error, lenth is let
var와 함께 사용되고, 실제 값이 사용되기 전까지 초기화를 지연시키는 것이다.let은 초기값이 반드시 존재해야 하기 때문에 lazy를 사용할 수 없다.lazy는 처음 사용될 때 값을 메모리에 올리고, 이후에는 그 값을 사용하기 때문에 computed property에는 사용할 수 없다./* lazy (초기화 지연) */
@IBOutlet private var cardButtons: [UIButton]!
var game: Concentration = Concentration(numberOfPairsOfCards: cardButtons.count/2) // error
// Cannot use instance member 'cardButtons' within property initializer; property initializers run before 'self' is available
// 프로퍼티 이니셜라이저가 self가 가능하기 전에 실행된다.
// cardButtons가 초기화 완료되고 나서, game에 접근할 때 초기화를 진행한다.
lazy var game: Concentration = Concentration(numberOfPairsOfCards: cardButtons.count/2)
stored property와는 다르게 값를 저장하지 않고, getter와 setter(optional)를 제공한다.
let은 값이 변경될 수 없기 때문에 computed property 앞에 올 수 없다.
var center: Point { // let 불가
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY) // return 생략 가능
}
set(newCenter) { // newCenter 생략 가능, 'newValue' is used as a default
origin.x = newCenter.x - (size.width / 2)
origin.y = newCenter.y - (size.height / 2)
}
}
// type extension 으로 자주 사용된다.
extension Int { //Int형 확장
var arc4random: Int { // read-only, 'get' 생략 가능
return Int(arc4random_uniform(UInt32(self))) // 0 ~ (self-1) 사이의 난수
}
}
property observer는 didSet, willSet 키워드와 함께 쓰이며, 프로퍼티의 값이 변경될 때마다 called 된다.
willSet은 값이 변경되기 직전에, didSet은 값이 변경된 직후 호출된다.
@IBOutlet weak var emojiCollectionView: UICollectionView! {
didSet {
emojiCollectionView.dataSource = self
emojiCollectionView.delegate = self
}
}
static이나 class 키워드가 붙은 프로퍼티를 의미한다.class는 override 가능하고, static은 불가능하다.Type.property로 접근 가능하다. lazy가 필요 없다.class SomeClass {
var storedInstanceProperty = "Instace value"
static var storedTypeProperty = "Type value"
static var computedTypeProperty: Int {
return 27
}
class var overrideableComputedTypeProperty: Int {
return 107
}
}
class someSubClass: SomeClass {
override static var storedInstanceProperty = "Instace value" // error: cannot override stored property
override static var computedTypeProperty: Int { // error: cannot override static property
return 30
}
override class var overrideableComputedTypeProperty: Int {
return 1
}
}
struct Point {
var x = 0
var y = 0
mutating func moveBy(x deltaX: Double, y deltaY: Double) { // mutating 키워드가 없으면 error
x += deltaX
y += deltaY
}
}
static이나 class 키워드가 붙은 메서드를 의미한다.class는 override 가능하고, static은 불가능하다.Type.property로 접근 가능하다.class SomeClass {
static func someTypeMethod() {
// type method implementation goes here
}
class func overrideableTypeMethod() {
// type method implementation goes here
}
}
SomeClass.someTypeMethod()
class someSubClass: SomeClass {
override static func someTypeMethod() { } // error, cannot override static func
override class func overrideableTypeMethod() {
// override here
}
}
https://docs.swift.org/swift-book/LanguageGuide/Properties.html
https://docs.swift.org/swift-book/LanguageGuide/Methods.html