ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Swift 구조체와 클래스 3 저장 속성, 지연 저장 속성, 계산 속성, 타입 속성, 프로퍼티 감시자
    Swift 2023. 1. 4. 16:19


    속성(프로퍼티): 속성은 값을 특정 클래스, 구조체 또는 열거형과 연결해준다.

    • 저장 속성: 상수 및 변수 값을 인스턴스의 일부로 저장 (클래스, 구조체)
    • 계산 속성: 값을 저장하는 대신 계산 (클래스, 구조체, 열거형)
    • 타입 속성: 속성들이 타입 자체와 연관 되어 있는 것


    1. 저장 속성
    각 인스턴스가 가지는 고유의 데이터 저장공간이고 변수나 상수로 선언이 가능하고 반드시 값을 가져야한다!
    클래스 또는 구조체의 인스턴스와 연관된 값을 저장하는 속성.
    var를 사용하면 변수 저장 속성, let을 사용하면 상수 저장 속성!
    (클래스 , 구조체 설명 참고)
    * 값 타입인 구조체의 인스턴스를 만들고 해당 인스턴스를 상수에 할당하면 변수 속성으로 선언된 경우에도 인스턴스의 속성을 수정할 수 없다.
    * 참조 타입인 클래스의 경우에도 마찬가지로 참조 유형의 인스턴스를 상수에 할당하는 경우에도 해당 인스턴스의 변수 속성을 수정할 수 있다.



    2. 지연 저장 속성
    초기값이 처음 사용될 때까지 계산되지 않는 속성!
    저장 속성과 달리 처음부터 메모리 공간을 가지지 않는다.
    아래의 코드에서 처럼 지연 저장 속성인 age를 호출 해줘야 값을 초기화하고 저장!
    lazy 키워드를 사용하고 선언 시점에 반드시 초기화 값을 저장해줘야 한다는 것!
    초기화 값을 저장해야하는 이유는?
    접근 시점에 메모리에 설정되는 부분이라 메모리에 할당되는 시점에 값이 필요하기 때문

    그리고 var(변수) 선언만 가능하다!
    이유는 ? 상수는 인스턴스가 완전히 생성되기 전에 초기화 해줘야하기 때문

    지연 저장 속성을 사용하는 이유는 뭘까?
    1. 메모리를 많이 차지할때
    2. 다른 속성들에 의존하거나 이용해야 할때
    3. 불필요한 초기화를 방지


    3. 계산(연산) 속성
    실제 값을 저장하는 프로퍼티가 아니라, 특정 상태에 따른 값을 연산하는 속성
    - getter(get블록): 밖에서 접근해서 값을 얻기
    - setter(set블록): 밖에서 값을 세팅하기

    ❓메서드가 아닌, 속성방식으로 구현하면 무슨 장점이 있을까?
    - 관련이 있는 두가지 함수를 한번에 구현 할 수 있다.
    - 인스턴스 외부에서 메서드를 통해 인스턴스 내부 값이 접근하려면 메서드를 2개(접근자, 설정자) 구현해야하는데
    분산 구현이 될 경우에는 가독성이 나빠질 수 있음! 또한 프로그래머의 입장에서 프로퍼티가 메서드 형식보다 훨씬 간결하다고 할 수 있음!


    함수를 사용했을때와 계산 속성을 사용했을 때를 비교해보자!

    • 함수 사용해서 구현
    class Person {
        var birth: Int = 0
        //나이 계산하는 함수
        func getAge() -> Int {
            return 2023 - birth
        }
        //태어난연도 계산하는 함수
        func setAge(age: Int){
            self.birth = 2023 - age
        }
    }
    var person = Person()
    person.birth = 2003
    person.getAge() //20
    person.setAge(age: 21)
    person.birth //2002

    • 계산 속성을 이용한 구현
      getter: 값을 얻는다는 의미 , setter: 값을 넣는다는 의미
      아래와 같이 계산 속성을 사용하면 하나의 프로퍼티에 접근자와 설정자가 모두 모여있고,
      해당 프로퍼티가 어떤 역할을 하는지 좀 더 명확하게 표현 가능!
      아래의 new Value는 뭘까? 관용적인 표현으로 매개변수를 따로 표기하지 않을때 매개변수의 이름을 대신할 수 있음!
      new Value를 쓰지 않고 매개변수를 표현하고 싶으면 set 뒤에 ()를 사용하여 괄호내에 매개변수 이름을 선언해도됨!
    class Person1 {
        var birth: Int = 0
        var age: Int{
            get {
                return 2023 - birth
            }
            set {
                self.birth = 2023 - newValue
            }
        }
    }
    
    var bPerson = Person1()
    bPerson.birth = 2002
    bPerson.age //21

    위의 코드는 읽기/쓰기가 가능한 계산 속성이고 읽기만 가능한 계산 속성을 만들 수 있음
    읽기만 가능한 계산 속성(get만 있는)에서는 return 생략도 가능함!
    값을 set하는 것은 선택이 될 수 있지만, 값을 얻는 것은 필수조건!

    class Person {
        var birth: Int = 0
        var age: Int{
            get {
                2023 - birth
            }
        }
    }
    
    var aPerson = Person()
    aPerson.birth = 2002
    aPerson.age



    4. 프로퍼티 감시자(Property Observers)
    프로퍼티 감시자는 속성 값의 변화를 관찰하고 값이 변경됨에 따라 적절한 작업을 취할 수 있음.
    새로운 값이 속성의 현재 값과 동일한 경우에도 속성 값이 할당될 때마다 호출 함.
    어디에서 속성관찰자를 사용할 수 있을까?

    • 저장속성(지연저장속성은 관찰 안됨)
    • 상속받은 저장속성
    • 상속받은 계산속성

    willSet: 값이 변경되기 직전에 호출
    didSet: 값이 변경된 직후에 호출


    wilSet 사용해보기
    메모리 공간에는 "기본 상태메세지"가 들어있고, "2023"년으로 변경하기 바로 직전에 willSet이 실행

    class Year {
        var year: Int
        
        init(year: Int) {
            self.year = year
        }
        
        var statusMessage: String = "기본 상태메세지" {
            willSet(newYear) {
                print("\(year)이 \(newYear)로 변경 될 예정입니다.")
            }
        }
    }
    
    let newyear = Year(year: 2022)
    newyear.statusMessage = "2023"
    
    //2022년이 2023으로 변경 될 예정입니다.


    didSet 사용해보기

    class Feeling {
        
        var myFeeling: String = "우루루루우울해 "
        
        var newFeeling: String {
            didSet {
                print("지금 \(myFeeling)한 기분이 \(newFeeling)으로 변경 되었습니다.")
            }
        }
        
        init(newFeeling: String){
            self.newFeeling = newFeeling
        }
        
    }
    
    let today = Feeling(newFeeling: "오늘은 행복해") //초기화 할때는 호출이 되지는 않음.
    today.newFeeling = "짱짱 행복해"
    //지금 우루루루우울해 한 기분이 짱짱 행복해으로 변경 되었습니다.


    *didSet과 WilSet은 매개변수를 설정 하지 않았을때
    willSet은 newValue, didSet은 oldValue가 자동으로 지정된다!


    5. 타입 속성
    타입자체에 속하는 속성을 정의 할 수 있음!
    저장 속성과 달리 항상 정의하는 타입속성 기본값을 제공해야 하는데
    그 이유는! 타입 자체에는 초기화 시 저장된 형식 속성에 값을 할당할 수 있는 초기화 프로그램이 없기 때문!
    지연 속성의 성격을 가짐 ⭐️ 저장 타입속성은 기본적으로 지연 속성
    (속성에 처음 접근하는 순간에 초기화됨)이지만, lazy라고 선언할 필요는 없음)
    타입 속성은 특정 인스턴스에 속한 속성이 아니기 때문에 인스턴스 이름으로는 접근불가(타입이름 + 속성으로 접근이 가능 Type.property)

    • 저장 타입속성: 인스턴스가 동일하게 가져야하는 보편적인 속성이나 공유해야하는 성격에 가까운 저장 속성을 저장 타입 속성으로 선언 하면 되고, 단순하게 static 키워드만 붙이면 된다. static은 고정적인/ 고정된 이라는 의미를 가지고있다. 상속 기능은 되지만, 상속할때 재정의가 불가능하다. let/var 둘다 선언이 가능하다. 지연저장 속성의 성격을 가진다. 호출할 때 메모리를 가짐!
    • 계산 타입속성: 상속시 재정의가 가능하고, static 키워드 말고 class 도 사용 가능! 어차피 계산속성이기때문에 let을 선언할 수 없다. 그때그때 마다 계산을 하기때문!
      메서드이기때문에 메모리 공간이 할당 되어 있지 않다!


    저장 타입속성 사용해보기

    class Climbing {
        
        //저장타입속성
        static var climbingShoesBrand: String = "라스포르티바"
        
        var shoesName: String
        var price: Int
        
        init(shoesName: String, price: Int) {
            self.shoesName = shoesName
            self.price = price
        }
        
    }
    
    let shoes = Climbing(shoesName: "타란튤라", price: 90000)
    shoes.shoesName //타란튤라 
    shoes.price //90000
    
    //선언된 타입속성에 접근하고 싶으면 .(점)을 찍어서 타입의 이름으로 접근
    Climbing.climbingShoesBrand //라스포르티바 


    계산 타입속성 사용해보기
    계산 타입 속성은 실질적은 메서드 역할을 한다!

    class Climbing {
        
        //저장타입속성
        static var climbingShoesBrand: String = "라스포르티바"
        static var week: Int = 5
        static var workday: Int = 3
        
        //계산타입속성(읽기 전용)
        static var sportDay: Int {
            return week - workday
        }
        
        var shoesName: String
        var price: Int
        
        init(shoesName: String, price: Int) {
            self.shoesName = shoesName
            self.price = price
        }
        
    }


    어떤 경우에 타입속성을 선언하면 좋을까?

    • 모든 인스턴스가 동일하게 가져야 하는 속성이거나 공유해야하는 성격에 가까울 때



    참고 도서 📚
    야곰 스위프트 5
    참고 사이트
    https://docs.swift.org/swift-book/LanguageGuide/Properties.html

    댓글

Designed by Tistory.