Property [연산] - ehrldyd15/Swift_Skills GitHub Wiki

Property [연산]

연산프로퍼티

클래스, 구조체, 열거형에서 사용된다.

저장프로퍼티와는 달리 따로 저장공간을 갖지 않으며 다른 저장프로퍼티의 값을 읽어 연산하거나 프로퍼티로 전달받은 값을 다른프로퍼티에 저장한다.

따라서 항상 var로 선언되어야 한다.

var name: Type {
    get {           ✅ // getter(다른 저장 연산프로퍼티의 값을 얻거나 연산하여 리턴할 때 사용)
        statements

        return expr
    }
    set(name) {     ✅ // setter(다른 저장프로퍼티에 값을 저장할 때 사용)
        statements
    }
}

연산프로퍼티는 위와 같은 생김새라고 보면 된다.

연산프로퍼티는 어떠한 값을 저장하는게 아니기 때문에 타입 추론을 통해 형식을 알 수 없다.

따라서 선언할때는 타입 어노테이션을 통해 자료형을 명시해야 한다.

그리고 선언된 자료형 뒤에는 {}를 붙여서 사용한다.

여기서는 어떤 타입의 값을 받아서 다른 저장프로퍼티에 저장할 것인지, 어떤 타입의 값을 리턴할 것인지 명시해주어야한다는 것이 핵심이다.

class Person {
    var alias: String {
        get { ❌
            return alias ❌
        }
        set(name) { ❌
            self.alias = name
        }
    }
}

위의 예제를 살펴보자

위처럼 작업하면 에러가 발생한다.

alias라는 연산프로퍼티는 값을 저장할 저장공간이 없는데 alias에 저장된 값을 읽으려고 하기 떄문이다.

class Person {
    var name: String = "ABC" ✅
 
    var alias: String {
        get {
            return name
        }
        set(name) {
            self.name = name
        }
    }
}

name같은 읽거나 쓸 수 있는 저장프로퍼티가 먼저 존재해야 하고,

연산프로퍼티에선 이 다른 저장프로퍼티의 값을 읽거나 쓰는 작업을 해야한다.

class Person {
    var name: String = "ABC"
 
    var alias: String { ✅
        get {
            return self.name + "는 이름"
        }
        set(name) { ✅ // 참고로 파라메터 name의 타입을 따로 지정하지 않는 이유는 alias를 선언할떄 명시해주었기 떄문이다.
                          또한, 피라메터의 이름은 name 말고 임의대로 아무거나 사용할 수 있다.
            self.name = name + "는 천재다."
        }
    }
}

let person: Person = .init()

print(person.alias) // ABC는 이름 ✅ get에 접근

person.alias = "나"
print(person.name)  // 나는 천재다. ✅ set에 접근

위의 예제 처럼 사용하면 되겠다.

var name: String = "ABC"

var alias: String {
    get {
        return self.name + "는 이름"
    }
    set { ✅
        self.name = newValue + "는 천재다." ✅
    }
}

위의 예제는 set의 파라메터를 생략했다. 파라메터 대신 newValue를 사용하면 된다.

class Person {
    var name: String = "ABC"
 
    var alias: String {
        get {
            return self.name + "는 이름"
        }
    }
}

setter를 생략할 수 있다. 그냥 읽기만 가능하다고 하여 get-only라고 하는데

class Person {
    var name: String = "ABC"
    
    var alias: String {
        return self.name + "는 이름"
    }
}

이렇게 get 자체를 생략할 수 있다.

당연하겠지만 set이 없기 때문에

person.alias = "나" ❌ // error: Cannot assign to property: 'alias' is a get-only property

해당 오류가 발생한다.

var alias: String {
    set { ❌ // set-only는 불가능하다. error: Variable with a setter must also have a getter
        self.name = newValue + "는 천재다"
    }
}

set-only는 불가능하다. 반드시 getter를 지녀야 한다는 에러가 발생한다.

참고자료

https://babbab2.tistory.com/119?category=828998