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
}
}