struct FixedLengthRange {
//저장 프로퍼티
var firstValue: Int
let length: Int
}
// 상수로 생성된 구조체 인스턴스는 프로퍼티가 변수여도 수정이 불가능
// 클래스 인스턴스는 상수로 생성돼도 수정 가능
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
rangeOfFourItems.firstValue = 6 //error
lazy
수정자를 붙여 나타낸다.프로퍼티 상수는 초기화가 완료되기 전에 항상 값을 가지고 있어야 하므로 lazy로 선언할 수 없다
class DataImporter {
var filename = "data.txt"
}
class DataManager {
lazy var importer = DataImporter()
var data = [String]()
}
let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
print(manager.importer.filename)
DataManager
인스턴스가 ataImporter
인스턴스를 처음 사용하는 경우에 생성하는 것이 더 합리적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))
//사각형 센터를 연산 프로퍼티를 통해 get
let initialSquareCenter = square.center // (5.0, 5.0)
//사각형 센터를 연산 프로퍼티를 통해 set
square.center = Point(x: 15.0, y: 15.0) // (10.0 , 10.0)
setter
가 새로운 값을 설정하는데 이름을 정의하지 않았다면 newValue
라는 기본 이름이 사용 ex) 위코드에서 newCenter
를 설정해주지 않았다면 newValue
이름으로 자동적으로 설정getter
의 전체 바디가 단일 표현식이라면 getter
는 암시적으로 표현식을 반환getter
만 있는 연산 프로퍼티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)
fourByFiveByTwo.volume // 40
willSet
은 값이 저장되기 직전에 호출
didSet
은 새로운 값이 저장되자마자 호출
willSet
구현의 일부로 이 파라미터에 특정 이름을 가질 수 있다 willSet
관찰자는 상수 파라미터로 새로운 프로퍼티 값이 전달didSet
관찰자는 예전 프로퍼티 값을 포함한 상수 파라미터가 전달oldValue
인 기본 파라미터 명을 사용.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
TwelveOrLess
구조체는 래핑하는 값이 항상 12와 같거나 더 작은 숫자가 됌. 더 큰 숫자를 저장하도록 하면 12가 저장
@propertyWrapper
struct TwelveOrLess {
private var number = 0
var wrappedValue: Int {
get { return number }
set { number = min(newValue, 12) }
}
}
속성으로 프로퍼티 전에 래퍼의 이름을 작성하여 프로퍼티에 래퍼를 적용.
다음은 항상 12 이하인지 확인하기 위해 TwelveOrLess
프로퍼티 래퍼를 사용하여 사각형을 저장하는 구조체
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"
@TwelveOrLess
를 작성하는 대신에 TwelveOrLess
구조체에 명시적으로 프로퍼티를 래핑
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 }
}
}
static
키워드로 타입 프로퍼티를 정의class
키워드를 대신 사용하여 하위 클래스에서 상위 클래스의 구현을 재정의 가능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
}
}