프로퍼티

  • 프로퍼티는 값에 대한 저장 여부를 기준으로 저장 프로퍼티, 연산 프로퍼티로 나뉜다.
  • 소속에 따른 기준으로 인스턴스 프로퍼티, 타입 프로퍼티로 나뉜다.

저장 프로퍼티

  • 일반적인 변수 혹은 상수가 저장 프로퍼티에 해당한다.
  • 저장 프로퍼티는 입력된 값을 저장하거나 저장된 값을 제공하는 역할을 한다.
  • 변수 및 상수를 통해 정의 가능하다.
  • 클래스와 구조체에서는 사용이 가능하지만 열거형에서는 사용이 불가하다.
  • 변수 혹은 상수 키워드 앞에 lazy를 붙이면 프로퍼티가 사용되는 시점에서야 프로퍼티가 초기화된다. (일반적인 경우 인스턴스가 생성됨과 동시에 모든 프로퍼티도 초기화된다.)
  • 저장 프로퍼티중에서는 로직이나 연산을 통한 값을 저장해야할 경우가 있는데, 이와 같은 경우에 클로저를 사용한다.
  • 연산 프로퍼티와 비슷하지만, 처음 프로퍼티가 생성될 때 단 한 번만 값을 평가한다.
class Exam {
    var property = { () -> Void in //클로저를 이용한 변수 생성
        print("생성")
    }()
    
}

var exam: Exam = Exam() //"생성" 출력
exam.property //아무런 일도 일어나지 않음

연산 프로퍼티

  • 특정 연산을 통해 값을 만들어 제공한다.
  • 변수만 사용이 가능하다.
  • 클래스, 구조체, 열거형에서 모두 사용이 가능하다.
  • 연산 프로퍼티의 값을 참조하기 위해서는 get 구문을 사용한다.
  • 연산 프로퍼티에 set 구문을 추가하면 값을 할당하거나 변경할 수 있다.
  • get은 연산 프로퍼티가 값을 반환하는 기능을 하기 위해서 필수이며, set은 선택적이다.
  • get 구문만 있다면 get 키워드는 생략이 가능하다.
class Plus {
    var num1: Int = 1
    var num2: Int = 2
    var result: String = "안녕"
    
    var num3: String {
        get {
            return result
        }
        set(newNum) {
            result = String(Int(newNum)! + self.num1 + self.num2)
        }
    }
}

var plus = Plus()
plus.num3 //안녕
plus.num3 = "10"
plus.result //13
  • 일종의 함수적인 역할을 하는 연산 프로퍼티는 프로퍼티이기는 하지만 다른 프로퍼티와의 관계가 의존적인 경우에 사용한다.
  • 예를 들면 도형의 중심 좌표는 도형의 기준 좌표 x, y와 가로, 세로 길이에 의존적이기 때문에 저장 프로퍼티보다는 연산 프로퍼티로 쓰이는 것이 훨씬 합당하다.
  • 물론 저장 프로퍼티를 쓸 수 있지만 연산 프로퍼티는 자동적으로 이 관계속에서 계산을 할 수 있어 코드의 반복을 줄일 수 있다.

프로퍼티 옵저버

  • 프로퍼티 옵저버란 프로퍼티의 상태를 지속적으로 관찰하여 값이 변하였거나, 변할경우 각각 이전의 값, 미래의 값을 전달하는 기능을 한다.
  • didSet, willSet 구문으로 사용 가능하다.
struct StudentA {
    var score: Int = 93 {
        didSet {
            print("중간고사 점수가 \(oldValue)점으로부터 \(score)점으로 바뀌었습니다.")
        }
        willSet {
            print("기말고사 점수는 \(score)점으로부터 \(newValue)점까지 올릴 계획입니다.")
        }
    }
}

var studentA: StudentA = StudentA()
studentA.score = 80 //중간고사 점수가 93점으로부터 80점으로 바뀌었습니다. 기말고사 점수는 80점으로부터 93점까지 올릴 계획입니다.
  • didSet과 willSet은 항상 같이 사용되어야 하는 것은 아니다.
  • 선택적으로 사용하되, 프로퍼티 변화에 따라 쓰임새를 정확히 해야한다.

타입 프로퍼티

  • 앞서 배운 프로퍼티는 인스턴스를 생성한 후에 사용해야 하기에 인스턴스 프로퍼티이다.
  • 반면 타입 프로퍼티는 인스턴스를 만들지 않고 클래스나 구조체 자체에 저장되며, 모든 인스턴스가 사용이 가능한 것을 타입 프로퍼티라 한다.
  • 인스턴스 프로퍼티는 인스턴스마다 개별 프로퍼티를 가지지만, 타입 프로퍼티는 모든 인스턴스가 하나의 값을 가진다.
  • 타입 프로퍼티는 변수나 상수를 선언하는 키워드 var or let 앞에 static 키워드를 붙인다.
  • 타입 프로퍼티로 선언된 변수가 연산 프로퍼티일 경우 static 대신 class 키워드를 사용하면 하위 클래스에서도 사용이 가능한 타입 프로퍼티로 정의할 수 있다. (클래스에서만 사용 가능)
  • 타입 프로퍼티는 선언과 동시에 초기값을 반드시 지정해야만 한다. (인스턴스와 상관이 없기 때문에 초기화 과정에서 값을 할당할 수 없기 때문이다.)
class Apple {
    class var apple: Int { //타입 프로퍼티로 선언된 연산 프로퍼티
        return 100
    }
}

Apple.apple //100

struct Banana {
    static var banana: Int = 3 //타입 프로퍼티로 선언된 저장 프로퍼티
}

Banana.banana //3
  • 이처럼 static, class 키워드를 사용한 타입 프로퍼티의 경우는 인스턴스의 생성없이 바로 사용이 가능하다.