why?
매주 발표하는 모임에서 'self vs Self' 주제에 대해 발표를 하게 되었습니다.
반드시 해당내용이 아니여도 되고, 관련 내용을 공부해서 자신의 방식대로 발표를 하는 것이기 때문에,
기존의 딱딱한 비교 틀에서 벗어나 self 사용에 대해서 좀 더 깊은 고찰을 해보게되었습니다.
vs Self
아주아주 간단히 self와 Self에 대해 비교해보고 넘어가겠습니다.
self는 instance를 가르킵니다. ( ex. "aaaabbbb", 19, ...)
Self는 Type을 가르킵니다.. (ex. String, Int ...)
self의 사용(시점)
간단한 첫번째 예제코드를 살펴봅시다.
lazy var btn: UIButton = {
let b = UIButton()
self.btn.setTitle("Hello", for: .normal)
return b
}()
self.btn.backgroundColor = .black
변수 btn을 클로저로 정의해주고, 이후 배경색상을 검정색으로 설정한다라는 코드입니다.
클로저 내부 self와 바깥의 self는 서로 다른 self일까요?
이 부분은 뒤에서 설명해드리겠습니다.
그렇다면 일반적으로 프로젝트를 사용할 때 왜 self를 사용해서 코드를 짰을까요?
instance 내부에서 intsatnce 속성을 더 명확하게 가르키기 위한 목적으로 사용합니다.
프로젝트를 만들 때, 이러한 목적으로 대부분 사용되는 것 같습니다.
두번째 예제코드를 보겠습니다.
class ViewController: UIViewController {
var team: String = "MU"
var player: String = "JI SUNG PARK"
var uniformNumber: Int = 13
//var iSay: String = "i like" + self.uniformNumber + self.player + self.team
override func viewDidLoad() {
super.viewDidLoad()
}
}
ViewController class에 변수를 선언한 단순한 코드입니다.
여기서 변수 iSay는 선언이 될까요?
self는 1차적으로 인스턴스 초기화 시점에 접근할 수 없습니다.
속성이 기본값을 가지는 것을 컴파일러가 평가하는 시점은
init body에서 인스턴스 속성에 값을 추가하는 시점과 동일합니다.
이 말을 해석해보면,
인스턴스 속성에 값이 쓰여지는 시점은
self라는 값 자체가 아직 초기화가 되지 않았다는 것을 의미합니다.
때문에 여기서는 self를 사용할 수 없습니다.
마지막 예제코드를 보겠습니다.
class ViewController2 {
var team: String = "MU"
var player: String = "JI SUNG PARK"
var uniformNumber: Int = 13
init() {
self.team = "Tottenham"
self.player = "Son"
self.uniformNumber = 7
}
}
class 내부의 변수를 선언하고, 초기화를 사용하여 또 다시 변수를 선언하는 코드입니다.
'두번째 예제코드'에서 제가 말씀드린 내용이 맞다면,
여기서는 아직 초기화가 되지 않았으니,
self를 사용하면 컴파일러가 에러를 나타내야하는데,
여긴 에러를 나타내지 않습니다.
이건 단지 self에 접근하여 값을 쓰고 있기 때문에,
self를 사용한다고는 볼 수 없습니다.
init()가 호출된 직후, 인스턴스는 내용이 초기화되지 않은 상태지만,
분명한 메모리에 할당된 주소를 가지게 됩니다.
결론적으로,
인스턴스가 '완전히' 초기화되지 않았기 때문에 self를 사용할 수는 없지만,
분명한 메모리 주소를 가지고 있기 때문에 접근하여 값을 초기화할 수 있는 것이죠.
잠깐, 아직 클로저의 내부 self와 바깥의 self에 대해 정답을 말씀드리지 않았습니다.
다시 첫번째 예제코드를 다시 살펴봅시다.
lazy var btn: UIButton = {
let b = UIButton()
self.btn.setTitle("Hello", for: .normal)
return b
}()
self.btn.backgroundColor = .black
분명, 변수 안에 self를 사용했는데,
오류가 나지 않았습니다. 왜일까요?
이는 lazy 키워드로 속성 초기화 시점을 늦춰버렸기 때문에 self를 사용할 수 있습니다.
lazy 로 정의된 속성은 호출 시점에 초기화를 시작하기 때문에,
그 시점이 무조건 인스턴스 초기화 이후임이 보장됩니다.
인스턴스 초기화가 완료되었다면 self 를 사용할 수 있으므로 lazy 속성에서는 self를 사용할 수 있습니다.
결론적으로
self keyword는,
속성이 전부 초기화 된 후 시점을 잘 파악해서
적절하게 사용하는 것이 가장 좋을 것 같네요.
오류가 있거나, 피드백이 있다면 언제든지 댓글로 알려주세요!
감사합니다 :)
'iOS > Swift' 카테고리의 다른 글
for - in / forEach 차이점 (0) | 2023.01.14 |
---|---|
do catch문 (+ try) (0) | 2023.01.08 |
instance init / deinit (생성자, 소멸자) (0) | 2022.05.21 |