[Swift] - 변수에 대해 잘 알고 있는 것이 맞습니까?
변수에 대한 내용을 점검해보자.
https://medium.com/codex/swift-5-do-you-really-know-about-variables-6073d48fc468
변수는 변명의 여지 없이 프로그래밍에서 중요하고, 변수 없이 프로그래밍은 거의 불가능에 가까울 것이다. 처음 개발을 시작하는 개발자들도 변수와 함수를 가장 먼저 공부한다. 하지만 개발을 오래하고 개발 경력이 좀 됐다 하더라도 변수에 대해 잘 안다고 말할 수 있을까?
변수란?
데이터를 받거나 저장하는 데이터 컨테이너다.
변수 선언하는 방법
var name = "Yoojin"
var age: Int = 35
var height: Double = 8.9
var isTall: Bool = {
return height > 7
}()
변수를 선언하는 다양한 방법들이 있다.
변수 naming convention
1. 축약어를 사용하지 않는다.
mutableVariable
을 mutVar
로 사용한다던가, titleLabel
을 titleLbl
과 같이 사용하지 않는다. 물론 자기는 알기 쉽겠지만 코딩은 기본적으로 다른 사람과 협업하는 작업이며 다른 사람이 봤을 때 한 번에 알기 쉽게 설명적이고, 분명해야 한다. 이를 테스트하는 방법으로, 내가 작성한 코드를 다른 개발자에게 보여줘보면 된다.
2. bool 타입 변수의 이름은 단일 보조자로 시작하게 한다.
아래의 예제르 보자.
struct User {
var verifiedEmail: Bool
var activated: Bool
var haveAJob: Bool
}
let user = User(verifiedEmail: false, activated: true, haveAJob: true)
위 사용자의 프로퍼티에 접근하려면 아래와 같이 해야 한다.
user.verifiedEmail
user.activated
user.haveAJob
직접 읽으면 문법적인 오류가 있고 프로퍼티의 목적을 알기 어렵다는 것을 알 수 있다. 이를 아래와 같이 고치면 훨씬 좋다.
struct User {
var didVerifyEmail: Bool
var isActivated: Bool
var hasAJob: Bool
}
user.didVerifyEmail
user.isActivated
user.hasAJob
변수와 프로퍼티의 차이는?
기본적으로는 같은 것이다. 데이터 컨테이너 자체를 얘기할 때 변수라 한다. 그리고 객체의 데이터 컨테이너를 프로퍼티라고 하는 것이다.
class User {
var name: String
init(name: String) {
self.name = name
}
}
위의 예제에서 name
은 String타입의 변수이다.
let user = User(name: "Dylan")
user.name
그리고 user
는 name
프로퍼티가 있다.
Custom Getter, Setter
Swift는 변수의 게터와 세터를 커스텀할 수 있게 해준다. 기본적으로는 아래와 같다.
var name: String
name = "Dylan"
print(name)
이를 아래와 같이 커스터마이징 할 수 있다.
var contactDictionary = [String: String]()
var name: String? {
get { return contactDictionary["name"] }
set { contactDictionary["name"] = newValue }
}
name = "Dylan"
print(name)
위 코드에서는 name
의 값을 가져올 때, contactDictionary
에서 값을 갖오고, 값을 설정할 때는 contactDictionary
에 값을 설정한다.
연산 프로퍼티 vs 저장 프로퍼티
연산 프로퍼티와 저장 프로퍼티는 둘 다 setter와 getter가 있다. 여기에 추가로 연산 프로퍼티는 값을 가져오거나 값을 짱하기 전에 변수가 연산을 수행할 수 있게 한다.
var subtotal = 12.9
var tax = 1.95
var total: Double {
subtotal + tax
}
print(total) // 14.85
subtotal
과 tax
는 저장 프로퍼티다. 얘네들은 값을 변수에 저장하고, 호출되었을 때 이 값들을 반환한다.
반면 total
은 연산 프로퍼티다. total
이 호출되면 값을 가지고 연산을 해서 연산된 값을 리턴한다. 연산 프로퍼티는 값을 저장하는 것이 아니라 말 그대로 연산을 한다.
non-void 함수가 있을 때 computed 변수를 사용하는 이유?
var subtotal = 12.9
var tax = 1.95
var total: Double {
subtotal + tax
}
func getTotal() -> Double {
subtotal + tax
}
print(total) // 14.85
print(getTotal()) // 14.85
위의 total
과 getTotal()
은 같은 값을 리턴하며, 동작도 같다. subtotal
과 tax
가 이미 클래스에서 제공이 되었기 때문에 연산 프로퍼티를 사용하는 것만으로 충분하다. 동적인 값을 위해 non-void 함수를 사용하는 것에 대해 고려해봐야 한다.
var subtotal = 12.9
var tax = 1.95
var total: Double {
subtotal + tax
}
func getTotal(with deliveryFees: Double) -> Double {
subtotal + tax + deliveryFees
}
print(total) // 14.85
print(getTotal(with: 5.68)) // 20.53
print(getTotal(with: 3.36)) // 18.21
print(getTotal(with: 2.8)) // 17.65
위 코드에서 getTotal()
함수에 동적 값인 deliveryFees
를 전달할 수 있지만, 이 또한 total
변수를 이용해서 같은 작업을 구현할 수 있다.
Function Type 변수
변수는 함수를 포함해서 다양한 타입의 데이터를 저장할 수 있다.
class Order {
var getTotal: ((Double) -> Double)?
}
class Store {
let subtotal = 12.95
let tax = 2.34
func getTotal(with deliveryFees: Double) -> Double {
subtotal + tax + deliveryFees
}
}
let order = Order()
let store()
order.getTotal = store.getTotal
print(order.getTotal!(4.5))