본문 바로가기

스피드 문법정리

15. Property

Property

클래스, 구조체 안의 속성

Stored Properties

var name : Type = DefaultValue
let name : Type = DefaultValue
class Person {
    let name : String = "John Doe"
    var age : Int = 33
}

Explict Member Expression

인스턴스 다음 .을 통해 접근하고자 하는 속성에 접근 Dot Syntax(점 문법)이라고도 부르며 스위프트에서는 Explict Member Expression(명시적 멤버 표현식)이라고 부름

구조체 인스턴스를 상수에 저장하면 구조체에 포함된 모든 속성이 상수가 됨 -> 구조체의 가변선은 속성의 가변성에 영향을 줌

instanceName.propertyName
instanceName.peopertyName = NewValue
class Person {
    let name : String = "John Doe"
    var age : Int = 33
}

let p = Person()
p.name
p.age = 30

struct Person {
    let name : String = "John Doe"
    var age : Int = 33
}

var p = Person()
p.age = 30

Lazy Stored Properties

저장속성이 초기화 되는 시점 = 인스턴스 초기화 시점과 같음, 하지만 지연 저장 속성에 처음 접근하는 시점에 초기화

인스턴스가 초기화 된 시점 후 개별적으로 초기화 -> 항상 변수 저장 속성으로 선언

생성자에서 초기화 하지 않기 때문에 선언시점에 기본값을 저장

lazy var name : Type = DefaultValue

struct Image {
    init() {
        print("new image")
    }
}

struct BlogPost {
    let title : String = "Title"
    let content : String = "Content"
    lazy var attachment : Image = Image()
    
    let date : Date = Date()
    lazy var formattedDate : String = {
        let f = DateFormatter()
        f.dateStyle = .long
        f.timeStyle = .medium
        return f.String(from : date)
    }()
}

var post = BlogPost()
post.attachment // new image

Computed Properties

수학적 계산이 아닌 다른 속성을 기반으로 속성값이 결정됨, 저장속성은 값을 저장할 메모리 공간을 가지고 있으나 계산 속성은 메모리 공간이 없음

대신 다른 속성에 저장된 값을 읽어 필요한 계산을 실행 후 리턴하거나 속성으로 전달된 값을 다른 속성에 저장 -> 속성에 접근할 때 마다 다른 값이 리턴 될 수 있어 var로 선언

저장속성과 달리 선언 시점에 기본값을 저장할 수는 없음

getter, setter를 사용하려면 그 연산된 값을 저장할 변수가 반드시 있어야함

var name : Type {
    get {           //get block getter
        statements
        return expr
    }
    set(name) {     //set block setter
        statements
    }
}

class Person {
    var name : String
    var yearOfBirth : Int
    
    init(name : String, year : Int) {
        self.name = name
        self.yearOfBirth = year
    }
    var age : Int {
        get {
            let calendar = Calendar.current
            let now = Date()
            let year = calendar.component(.year, from : now)
            return year - yearOfBirth
        }
        set {
            let calendar = Calendar.current
            let now = Date()
            let year = calendar.component(.year, from : now)
            yearOfBirth = year - newValue
        }
    }
}

let p = Person(name : "John Doe", year : 2002)
p.age // 17

p.age = 50
p.yearOfBirth // 1969

Person 인스턴스를 p에 저장하고 이름과 년도를 저장할 경우 변수 age는 현재 날짜를 구한뒤 상수 year에 넣고 year(현재년도) - yearOfBirth(2002) 를 뺀 결과인 17이 나오고 이는 getBlock 만 실행하게 됨

age에 50을 넣게 되면 setBlock을 실행시키고 상수 year(현재년도) - newValue(새로운 나이 50)의 결과인 1969를 리턴

Read - only Computed Properties

읽기전용 계산 속성으로 쓰기전용 계산 속성은 없음

var name : Type {
    get {
        statements
        return expr
    }
}

var name : Type {
    statements
    return expr
}

클로져와 구별하는 방법은 자료형 뒤에 할당 연산자가 있다면 클로져, 없다면 읽기전용 계산 속성

var age : Int {
     get {
         let calendar = Calendar.current
         let now = Date()
         let year = calendar.component(.year, from : now)
         return year - yearOfBirth
     }
}

Property Observer

willSet - 값이 저장되기 직전에 호출, didSet - 새로운 값이 저장된 직후 호출

저장 속성에만 가능 -> 예제 width는 저장 속성

var name : Type = DefaultValue {
    willSet(name) {
        statements
    }
    didSet(name) {
        statements
    }
}

class Size {
    var width = 0.0 {
        willSet {
            print(width, =>, newValue)
        }
        didSet {
            print(oldValue, =>, width)
        }
    }
}

let s = Size()
s.width = 123 
// 0.0 => 123.0
// 0.0 => 123.0

Type Property

형식속성은 기본적으로 지연속성 -> 속성에 처음 접근하는 순간 초기화됨 

Stored Type Properties

static var name : Type = DefaultValue // Variable Stored Type Property
static let name : Type = DefaultValue // Constant Stored TYpe Property

TypeName.propertyName
class Math {
    static let pi = 3.14
}

let m = Math() // 이 순간 초기화가 아닌
m.pi // Error
Math.pi // 접근하는 순간 초기화 됨

Computed Type Properties

subclass 에서 overriding금지, class는 overriding 허용

static var name : Type {
    get {
        statements
        return expr
    }
    set(name) {
        statements
    }
}

class var name : Type {
    get {
        statements
        return expr
    }
    set(name) {
        statements
    }
}
enum Weekday : Int {
    case sunday = 1, monday, tuesday, wednesday, thursday, friday, saturday
    static var today : Weekday {
        let cal = Calendar.current
        let today = Date()
        let weekday = cal.component(.weekday, from : today)
        return Weekday(rawValue : weekday)!
    }
}

Weekday.today

Self

self는 현재 인스턴스에 접근하기 위해 사용하는 특별한 속성

self를 타입 맴버에서 사용하면 인스턴스가 아닌 형식 자체를 나타냄 

self
self.propertyName
self.method()
self.[index]
self.init(parameters)
class Size {
    var width = 0.0
    var height = 0.0
    
    func calcArea() -> Double {  // 속성에 접근할 시 생략
        return (self.)width * (self.)height
    }
    var area : Double {   // 메소드에 접근할 시 생략
        return (self.)calcArea()
    }
    func update(width : Double, height : Double) // 속성과 파라미터 구분을 위해서 사용
    	self.width = width
        self.height = height
    
    func doSomething () {  // 클로저 내부에서 속성에 접근할 때 사용
        let c = { self.width * self.height }
    }
    
    static let unit = ""
    static func doSomething() { // self를 타입 맴버에서 사용하면 인스턴스가 아닌 형식 자체를 나타냄
    	self.width  // Error / 형식메소드에서 인스턴스 속성에 직접 접근하는 것은 불가능
        (self.)unit
    }
    
    
}
struct Size {
    var width = 0.0
    var height = 0.0
    
    mutating func reset(value : Double) {
        width = value
        height = value
        self = Size(width : value, height : value) // 인스턴스가 새로운 인스턴로 교체 
                                                   // 생성자를 통해 초기화 가능 클래스에서는 불가능
    }
}

    

'스피드 문법정리' 카테고리의 다른 글

17. Inheritance and Polymorphism  (0) 2020.06.19
16. Method and Subscript  (0) 2020.06.19
14. Structure and Class  (0) 2020.06.18
13. Enumeration  (0) 2020.06.17
12. Collection  (0) 2020.06.16