Swift에서의 get과 set은 Java의 getter, setter와 동일한 기능을 합니다. 사용하는 이유도 거의 동일한 것 같았습니다. 외부에서 property에 직접적으로 접근하는 것을 막기도 하고 값을 변경(set)하기 전에 validation을 하기 위한 용도가 되기도 하구요.
다만 독특하게 computed property라고 하여 property 자체에 마치 method처럼 get과 set을 설정해 주게 됩니다.
var numberOfStudents: Int {
get{
return totalNumberInClass - 1
}
set {
print(newValue)
}
}
위의 구문처럼 사용하는데, 상당히 생소하게 느껴졌습니다 ㅎㅎ 곧 적응하겠지만요
이렇게 property의 값을 "계산"해서 저장하기 때문에 Computed property라고 부릅니다.
set{} 에서 사용된 newValue는 numberOfStudents 라는 property에 할당될 새로운 값을 지칭하는 키워드로, swift에서 제공하는 키워드입니다.
🏷 var myInt: Int = 10 과 같이 표기하는 경우는 Stored property라고 부릅니다.
별도의 계산이 이루어지지 않고 바로 값을 저장합니다.
1. get{} 사용하기
Java에서 사용하는 getter의 경우, 해당 변수의 값을 가져오기 위해 사용합니다. 예를 들어서, title이라는 String type 변수가 있고, getTitle()은 title 값을 반환합니다.
public class Question {
private String title;
//...
public String getTitle() {
return title;
}
}
하지만 Swift에서의 get은 Java의 getter처럼 생각하면 안되는 것 같습니다.
Java의 getter처럼 사용하려고 하면, 아래처럼 코드가 작성될 것입니다.
var title: String {
get {
return title
}
}
하지만 이렇게 한 다음 print(title)을 실행하면, 아래와 같은 에러가 발생합니다.
관련해서 찾아보니 자기 자신을 recursive하게 참조해서 문제가 발생하는 것이라고 합니다.
그렇기 때문에 실제로 값을 저장할 backing storage를 따로 두어야 합니다! 어떻게 사용하는 것인지 예시를 살펴보겠습니다.
//title의 backing storage
var _title: String = "Title"
//_title의 값을 title로 get 또는 set 한다.
var title: String {
get {
return _title
}
}
print(title)
title로 _title의 값에 접근하는 구조를 보여주고 있습니다.
get만 명시하고 set은 따로 명시하지 않게되면 해당 property는 get-only가 됩니다. 그래서 해당 property의 값을 변경하려고 하면 경고 메세지가 compile time에 나타납니다.
🏷 get-only computed property vs constant
let으로 선언된 property도 값 변경이 불가능한데, get-only var과의 차이는 무엇일까요?
관련된 궁금증에 대한 답이 아래에 잘 나와 있어서 링크를 가져왔습니다 :)
https://stackoverflow.com/questions/40637157/whats-the-point-of-read-only-variables-when-you-have-let
2. set{} 사용하기
property의 값을 바꿀 수도 있게 하려면 set{}을 사용하면 됩니다.
private var _title: String = "Title"
var title: String {
get {
return _title
}
set {
if newValue.count < 3 {
print("Title too short")
} else {
_title = newValue
}
}
}
새로 설정될 값의 길이가 3보다 작은 경우에는 "Title too short" 메세지를 보내며 값이 set되지 않도록 하고, 3이상인 경우에만 새로운 값(newValue)으로 set 되도록 로직을 작성하였습니다.
여기서 set이 가진 하나의 장점을 발견할 수 있는데, 바로 데이터 유효성 검사를 할 수 있다는 점입니다.
3. set{}을 이용한 data validation
예시를 하나 더 살펴보겠습니다.
var _numberOfStudents: Int = 9
var numberOfStudents: Int {
get{
return _numberOfStudents
}
set(newValue) {
if(newValue <= 10) {
print("new value must be bigger than 10.")
} else {
_numberOfStudents = newValue
print("new value set to \(newValue)")
}
}
}
numberOfStudents = 9
//Prints "new value must be bigger than 10."
numberOfStudents = 20
//Prints "new value set to 20"
위 예시에서는 newValue가 10 이하인 경우는 예외 처리를 하고, 그 외의 경우는 property의 값을 set하도록 유효성 검사를 해주었습니다.
4. 다른 property에 의존적인 property에 get, set 활용하기
get, set은 위의 예시처럼 사용할 수도 있고, 다른 property에 의존하여 값이 달라지는 property에도 적용할 수 있습니다.
한 명의 선생님이 최대 10명의 학생을 담당한다고 가정해 봅시다. 이 경우에는 학생 수의 증감에 따라 필요한 선생님의 수가 달라지게 됩니다. 즉, 필요한 선생님의 수는 학생 수에 의존하게 됩니다. 이 상황을 코드로는 아래 처럼 나타낼 수 있을 것입니다.
var _numberOfStudents: Int = 10
var numberOfStudents: Int {
get {
return _numberOfStudents
}
set {
if(newValue < 0) {
print("Must be bigger than 0")
} else {
_numberOfStudents = newValue
}
}
}
var numberOfTeachersNeeded: Int {
get {
return _numberOfStudents / 10
}
}
print(numberOfTeachersNeeded)
//Prints 1
현재 학생의 수는 10명이므로 필요한 선생님의 수는 1명으로 계산되어 나옵니다.
만약에 학생의 수를 100명으로 변환하면 필요한 선생님의 수는 10명으로 계산되어 나오게 됩니다.
numberOfStudents = 100
print(numberOfTeachers)
//Prints 10
이렇게 의존 관계에 있는 property를 계산할 때도 유용하게 사용될 수가 있습니다!
get{} 과 set{}에 대해 간단하게 알아보았습니다. 예전에는 이 개념을 들었을 때 잘 이해가 되지 않았는데, Java로 코딩에 대한 개념을 어느 정도 익혀서 인지 이번에는 훨씬 잘 이해가 되었습니다 ☺️
다음번에는 Observed property인 willSet과 didSet에 대해서 알아보도록 하겠습니다.
감사합니다!
•ɞ•
참고자료
'Swfit' 카테고리의 다른 글
Light, dark 모드 별 사용될 backgroundimage 설정하기 (0) | 2022.10.07 |
---|---|
Observed property: willSet & didSet (0) | 2022.10.04 |
[Realm] 데이터 저장하는 방법(Create) (0) | 2022.04.08 |
[Realm] 데이터 불러오는 방법(Read) (2) | 2022.03.30 |
Swift JSON Parsing하기 (2) | 2022.03.21 |