[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))
