그래도 클로저보다는 이해가 잘 되는듯 합니다?
이제 곧 개강인데 학교다니면서도 꾸준히 하도록 해보겠습니다 허허
그럼 가보실까요
Initializers
는 보통 '초기화'라고 합니다
음.. 이것도 예시를 바로 보는게 더 도움이 될 거같네요
한 개의 프로퍼티가 있는 User구조체가 있다고 해볼게요
struct User {
var username: String
}
여기서 인스턴스를 생성하려면 username
값을 줘야합니다
var users = User(username: "twostraws)
이렇게 말이죠
빼먹으면 에러가 나게됩니다
여기서 밑에 init(username:)
부분 보이시죠?
저게 바로 초기화와 관련된 부분인데요
실제로 작성을 하면 아래와 같이 됩니다.
struct User {
var username: String
init() {
username = "Anonymous"
print("Creating a new user!")
}
}
작성하면서 주의할 점은 init
구문이 끝나기전에 모든 프로퍼티에 값을 지정해줘야한다는 것입니다
이제 인자를 안 받아도 되면 아래와 같이 작성하면 됩니다
var user = User()
user.username = "twostraws"
첫 username
은 초기화에서 할당해준 기본값을 반환하고
두 번째 username
은 이후 할당해준 twostraws를 반환하는걸 확인했습니다.
메소드 내부에는 self
라고 하는 특별한 상수가 존재합니다.
이게 특히 프로퍼티와 이름이 같은 초기화를 해야할 때 유용하게 사용됩니다
코드를 한번 보실까요
struct Person {
var name: String
init(name: String) {
print("\(name) was born!")
self.name = name
}
}
name
프로퍼티를 가지는 Person
구조체입니다
그리고 name
매개변수를 받는 name
initializer를 작성하는데
self
이때 프토퍼티와 파라미터의 구분을 해줍니다
self.name
은 프로퍼티고 name
은 파라미터(매개변수)입니다
성능 최적화를 위해서 Swift는 몇몇 프로퍼티들을 필요할 때만 생성할 수 있도록 합니다.
예시로 FamilyTree
구조체를 보죠 단순한 구조체지만 가계도를 만드는데는 생각보다 시간이 들어갑니다
struct FamilyTree {
init() {
print("Creating family tree!")
}
}
그리고 FamilyTree
구조체는 Person
구조체에서 프로퍼티처럼 사용될 수도 있습니다
struct Person {
var name: String
var familyTree = FamilyTree()
init(name: String) {
self.name = name
}
}
var ed = Person(name: "Ed")
그런데 만약 가계도가 모든 사람에게 필요하지 않는다면 어떨까요?
familyTree
앞에 lazy
라는 키워드를 붙이면 됩니다
lazy var familyTree = FamilyTree()
그러면 접근을 할 때만 가계도를 생성하게 합니다
ed.familyTree
따라서 “Creating family tree!”을 보고싶다면 최소한번은 프로퍼티를 호출해야하는거죠
전체 코드입니다
우리가 여태 만든 모든 프로퍼티와 메소드는 구조체의 개별 인스턴스에 속하죠
그 말은 우리가 Student
라는 구조체를 만든다면 각각의 프로퍼티와 메소드를 가지는 개별 인스턴스를 만들 수 있다는 소립니다
struct Student {
var name: String
init(name: String) {
self.name = name
}
}
let ed = Student(name: "Ed")
let taylor = Student(name: "Taylor")
그리고 static
키워드를 통해 특정 프로퍼티와 메소드를 구조체의 모든 인스턴스가 공유할 수 있도록 할 수 있습니다
확인해보기 위해서 Student
구조체에 static property
를 추가해보죠
학생이 반에 학생이 몇명인지 나타낼 건데요.
새로 인스턴스를 생성할때 마다 1을 더해줄겁니다
struct Student {
static var classSize = 0
var name: String
init(name: String) {
self.name = name
Student.classSize += 1
}
}
그리고 classSize
인스턴스가 아니라 구조체에 속하기 때문에 호출할 때는 아래와 같이 해야합니다
print(Student.classSize)
값이 증가함을 확인할 수 있네요
Access control은 어떤 코드가 프로퍼티와 메소드를 사용할 수 있는지 제한하는 문법입니다
이게 중요한 이유는 어떤 프로퍼티들은 다른 코드가 읽게하고 싶지 않기 때문이죠
아래의 Person
구조체는 사회보장넘버를 저장하는 id
라는 프로퍼티를 가집니다
struct Person {
var id: String
init(id: String) {
self.id = id
}
}
let ed = Person(id: "12345")
당연하지만 이런 개인정보를 타인이 보게하면 안되겠죠?
그래서 private
키워드를 사용해 아래와 같이 코드를 수정했습니다
struct Person {
private var id: String
init(id: String) {
self.id = id
}
}
이렇게 하면 ed.id
를 해도 값을 읽을수가 없습니다
그렇죠?
그럼 이제 이걸 어떻게 해서 접근할 수 있느냐
Person
구조체 내부의 함수를 통해서만 접근할 수 있어요
struct Person {
private var id: String
init(id: String) {
self.id = id
}
func identify() -> String {
return "My social security number is \(id)"
}
}
이렇게 말이죠
public
이라는 옵션도 있는데요, 이건 다른 코드들이 프로퍼티와 메소드에 접근하게 해줍니다.
mutating
을 붙여줘야한다self
를 통해 메소드 내부의 최근 인스턴스를 참조할 수 있다lazy
키워드는 스위프트가 처음 사용할 때 프로퍼티를 만들도록 한다static
키워드로 모든 인스턴스에 프로퍼티나 메소드를 공유할 수 있다.