본문 바로가기
iOS/Swift

[구조체&클래스] 속성 - 계산 속성, 계산 타입 속성

by 나리._. 2021. 9. 10.

- 계산 속성

"계산 속성이 아닌 방식"으로 구현예시

class Person {
    var name: String = "사람"
    var height: Double = 160.0
    var weight: Double = 60.0
    
    func calculateBMI() -> Double {
        let bmi = weight / (height * height) * 10000
        return bmi
    }
}


let p = Person()
p.height = 165     // 키 165
p.weight = 65      // 몸무게 65

p.calculateBMI()   // 23.875

// BMI를 계산하는 이 산식은 파라미터가 없고,
// 내부에 가지고 있는 저장 속성값을 이용해, 계산한 후 결과값을 리턴한다.

 

위의 코드를 계산속성(Computed Properties)으로 바꾸어서 구현하기

class Person {
    var name: String = "사람"
    var height: Double = 160.0
    var weight: Double = 60.0
    
    var bmi: Double {
        get {        //getter ===> 값을 얻는다는 의미
            let bmi = weight / (height * height) * 10000
            return bmi
        }
//        set(bmi) {   //setter ===> 값을 세팅한다(넣는다)는 의미
//            weight = bmi * height * height / 10000
//        }
        set { // newValue 라는 파라미터로 쓰기로 (생략 가능)
            weight = newValue * height * height / 10000
        }
    }
    
    // 만약에 쓰기 계산속성(set)을 메서드로 구현했다면
//    func setWeightWithBMI(bmi: Double) {
//        weight = bmi * height * height / 10000
//    }

}


let p1 = Person()
p1.height = 165   // 키 165
p1.weight = 65    // 몸무게 65


p1.bmi // 23.875
p1.bmi = 25
p1.bmi // 25

 - 항상 다른 저장 속성에 의한 결과로 계산해 나오는 그런 방식의 메서드인 경우 아예 속성처럼 만들 수 있다. (===> 계산 속성)

 - 계산 속성 ===> 구조체, 클래스, (열거형) 동일

 - 항상 변하는 값이므로, var로 선언해야함 (let로 선언불가)

 - 자료형 선언을 해야함(형식추론 형태 안됨) (메서드이기 때문에 파라미터, 리턴형이 필요한 개념)

 - get은 반드시 선언 해야함(값을 얻는 것은 필수, 값을 set하는 것은 선택)

 - 읽기만 가능한 계산속성(read-only)은 get블록을 생략 가능

  get블록만 있다면, 굳이 한번 더 감쌀 필요가 없다. ===> 편의를 위해 get을 생략가능

  var bmi: Double {

      let bmi = weight / (height * height) * 10000

      return bmi

  }

 

 

그렇다면 메서드가 아닌, 속성방식으로 구현하면 무슨 장점이 있을까?

 

 - 관련이 있는 두가지 메서드(get, set)를 한번에 구현할 수 있다.

 - 그리고 외부에서 보기에 속성이름으로 설정가능하므로 보다 명확해 보인다.

 따라서, 계산 속성은 메서드를 개발자들이 보다 읽기 쉽고, 명확하게 쓸 수 있는 형태인 속성으로 변환해 놓은 것이다.

 

 - 실제로, 계산 속성은 겉모습은 속성(변수)형태를 가진 메서드(함수)임 ⭐️

 - 계산 속성은 실제 메모리 공간을 가지지 않고, 해당 속성에 접근했을때 다른 속성에 접근해서 계산한후,

   그 계산 결과를 리턴하거나 세팅하는 메서드 이다. (메모리 - 메서드구조)

 

 

- 계산 타입 속성

class Circle1 {
    
    // 저장 타입 속성
    static let pi: Double = 3.14
    static var count: Int = 0
    
    
    // (계산) 타입 속성(read-only)
    static var multiPi: Double {
        return pi * 2
    }
    
    // 저장 속성
    var radius: Double     // 반지름
    
    
    // 생성자
    init(radius: Double) {
        self.radius = radius
        // Circle.pi = 1
    }
    
}


let b = Circle1.multiPi // 6.28

그렇다면, 어떤 경우에 타입 속성을 선언해야 하나?

➡︎ 모든 인스턴스가 동일하게 가져야 하는 속성이거나(해당 타입의 보편적인 속성), 모든 인스턴스가 공유해야하는 성격에 가까운 경우!

 

계산 타입 속성 ===> 상속에서, 상위클래스에서 class키워드를 붙인 경우, 재정의 가능

 - class키워드(계산 타입 속성만) ⭐️

 - 상속이 있는 경우, 계산 타입 속성에서는 static대신 class키워드를 사용(===>static과 동일한 역할)하면 재정의 가능한 속성이 된다.