SMALL
[ 객체를 만들기 위한 여러 가지 초기화 방법 ]
초기화와 생성자
초기화는 클래스, 구조체, 또는 열거형의 인스턴스를 생성하고
속성을 초기화하여 사용할 수 있도록 하는 과정을 의미
Swift에서 초기화는 객체가 메모리에 할당되고
속성이 적절히 설정되어 안정적으로 사용될 수 있도록 하는 중요한 단계
인스턴스란?
객체 지향 프로그래밍에서, 인스턴스(Instance)는 클래스,
구조체 또는 열거형과 같은 타입의 실제 예시를 나타냄
클래스나 구조체 등의 템플릿(틀)을 기반으로 생성된 실제 데이터를 가리킴
즉, 클래스나 구조체를 기반으로 만들어진 객체를 "인스턴스" 라고 부름
// Person 클래스 정의
class Person {
var name: String
var age: Int
// class로 정의된 부분이니 init으로 초기화를 해주어야 합니다.
init(name: String, age: Int) {
self.name = name
self.age = age
}
func greet() {
print("Hello, my name is \(name) and I'm \(age) years old.")
}
}
// Person 클래스의 인스턴스 생성 = init을 사용해주면 됩니다.
// 아래 두 상수를 2개의 인스턴스라고 할 수 있습니다.
let john = Person(name: "John", age: 30)
let emily = Person(name: "Emily", age: 25)
// 생성된 인스턴스 사용
john.greet() // 출력: Hello, my name is John and I'm 30 years old.
emily.greet() // 출력: Hello, my name is Emily and I'm 25 years old.
초기화 방법
기본 초기화(Default Initialization)
Swift에서는 클래스의 속성이 기본 값으로 초기화되는 것을 지원
이는 클래스의 모든 속성이 기본 값을 가지고 있을 때 자동으로 발생
// 기본 초기화 예시
class Person {
var name: String = ""
var age: Int = 0
}
/*
위에서 name의 빈문자열, age에 0이 들어있다면, init을 만들지 않아도 무관합니다.
이유는 이미 값이 다 들어가 있기 때문입니다. 그리고 Person()를 해주면 빈문자열과 0이 들어간 객체가
생성이 되어 있는 것입니다.
*/
let person = Person() // 기본 초기화
지정 초기화(Designated Initialization)
init 키워드를 사용하여 클래스의 모든 속성을 초기화하는 메서드
class Person {
var name: String
var age: Int
// 타입만 지정되어있으니 init으로 초기화를 시켜주어야 합니다.
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
let person = Person(name: "John", age: 30) // 지정 초기화
편의 초기화(Convenience Initialization)
기본 초기화 또는 지정 초기화를 간편하게 호출하는 보조 메서드
class Person {
var name: String
var age: Int
// 타입만 지정되어 있으니 init 초기화를 해주어야 합니다.
init(name: String, age: Int) {
self.name = name
self.age = age
}
convenience init(name: String) { // convenience init은 내부에 자체적으로 지정생성자를 반드시 호출해야 합니다.
self.init(name: name, age: 0) // 자체지정생성자 || 형식은 반드시 동일
/*
convenience가 붙은 이유는 age를 항상 0으로 설정하기 위해서 입니다. 즉, 클래스를 찍어낼 때마다
age를 0을 넣는 행위 자체가 귀찮은 것입니다.
*/
}
}
let person = Person(name: "Alice") // 편의 초기화 사용
// Person(name: "Alice")는 name만 받고 age는 0으로 세팅이 되어있는 상태가 됩니다.
강제 해제(Force Unwrapping)되지 않는 옵셔널 초기화
옵셔널 타입을 가진 속성은 선언과 동시에 초기화되거나 나중에 값을 할당 가능
class Person {
var name: String? // 옵셔널에는 값을 넣어주지 않아도 되는가? -> 자동으로 nil이 들어가 있는 상태입니다.
var age: Int = 0
}
let person = Person()
person.name = "Emily"
person.age = 25
실패 가능 생성자
기존 생성자는 컴파일 시점에 모든 프로퍼티가 초기화 되어야 하기 때문에
초기화 실패의 경우, 컴파일 에러가 발생
하지만 실패 가능 생성자(Failable Initializer)는 초기화에 실패하더라도
에러가 발생하지 않고 nil을 리턴, Optional한 생성자
// class의 실패 가능 생성자
class UserProfile {
let username: String
// 실패 가능 생성자: 유효하지 않은 이름을 사용할 경우 초기화 실패
init?(username: String) {
/*
username가 5자 이상이면 self.username가 성공, 5자 미만일 경우 return nil 이부분이 호출됨.
그러므로 (username: "user123") 이부분을 생성을 했을 때 user123은 7이니까 validProfile의
값은 UserProfile가 바인딩이 되며, else 부분은 실행 되지 않습니다.
*/
// 유효한 사용자 이름인지 확인 || 필터링 기능
guard username.count >= 5 else {
return nil // 입력된 사용자 이름이 유효하지 않을 경우 초기화 실패
}
self.username = username
}
}
// 실패 가능 생성자를 사용하여 인스턴스 생성
if let validProfile = UserProfile(username: "user123") {
print("Valid username: \(validProfile.username)")
} else {
print("Invalid username. Username should be at least 5 characters long.")
}
if let invalidProfile = UserProfile(username: "user") {
// 여기서의 user는 길이가 4입니다. 그렇기 때문에 UserProfile(username: "user") 여기는 nil이 됩니다.
// 당연히 invalidProfile 이곳엔 바인딩이 되지 않고 else가 실행되어 "... 5 characters ..."가 출력됩니다.
print("Valid username: \(invalidProfile.username)")
} else {
print("... 5 characters ...")
}
// struct의 실패 가능 생성자
struct Animal {
let name: String
init?(name: String) {
if name.isEmpty { // name이 비어있는지(isEmpty) 확인해보고 빈문자라면 nil 아니면 성공
return nil // 생성자 내에서 실패 가능 부분에 nil을 리턴하면 됨
}
self.name = name
// 성공했을 경우 인스턴스가 생성이 됩니다. 하지만 Animal 타입이 아닌 'Animal 옵셔널' 타입 입니다.
// 이유 = name이 nil을 뱉어줄 가능성이 있기 때문입니다.
}
}
let animal1 = Animal(name: "choco") //인스턴스 생성. 타입은 Animal? 이다
let animal2 = Animal(name: "") // 문자열이기에 유효한 타입이지만 nil이 리턴된다
// enum의 실패 가능 생성자
enum key {
case feet
case centiMeter
init?(symbol: String) {
switch symbol { // symbol이 f인지 cm인지 다른값이 들어왔는지..
case "f": // 정확히 소문자 f
self = key.feet
case "cm": // 정확히 cm
self = key.centiMeter
default:
return nil
}
}
}
let feet: key = key.feet // key 타입
/*
여기서의 .feet은 가장 처음에 생성한 케이스 feet을
직접적으로 넣어준 것이기 때문에 타입은 key 타입이 됩니다.
*/
let centi: key? = key(symbol: "cm")
/*
init? 초기화자를 사용한다면 symbol을 넣어 주어야합니다. 이때의 타입은 key 옵셔널 타입입니다.
이유는 리턴을 nil을 할 수 있기 때문입니다.
*/
let feet2: key? = key(symbol: "F") // nil
728x90
'IOS > Swift-Study' 카테고리의 다른 글
[Swift-Study] 심화 문법종합반 2주차 1일차 정리 - 타입 캐스팅 (0) | 2024.03.12 |
---|---|
[Swift-Study] 심화 문법종합반 2주차 1일차 정리 - 프로퍼티 옵저버 (0) | 2024.03.12 |
[Swift-Study] 기초 문법종합반 1주차 4일차 정리 - 상속 (0) | 2024.03.12 |
[Swift-Study] 기초 문법종합반 1주차 3일차 정리 - 클래스, 구조체, 열거형 (0) | 2024.03.12 |
[Swift-Study] 기초 문법종합반 1주차 3일차 정리 - 객체 지향 (0) | 2024.03.12 |