2024년 3월 12일 화요일
클래스의 상속 개념과 객체를 만들기 위한 다양한 초기화 방법에 대해 공부해 봅니다.
#1. inheritance (상속)
#2. initializer (초기화)
#1. inheritance (상속)
- 클래스 간에 코드 및 속성을 공유하는 메커니즘을 제공: 기존 클래스에서 새로운 클래스를 만들고, 기존 클래스의 특성(속성과 메서드)을 재사용하면서 새로운 기능을 추가할 수 있도록 해준다.(서브 클래싱)
- 코드 재사용성: 기존 클래스의 특성을 재사용하여 중복을 피하고 유지보수성을 높일 수 있다.
- 계층 구조: 부모 클래스와 이를 상속받는 자식 클래스 간에 계층 구조를 형성하여 다양한 추상화와 분류 가능
- override (재정의)
- 부모 클래스에서 '상속받은' 메서드, 속성 또는 서브스크립트를 자식 클래스에서 다시 정의할 때 사용
- 자식 클래스에서 부모 클래스의 메서드를 재정의하여 새로운 구현을 제공할 수 있다.
- super (호출)
- 자식 클래스에서 부모 클래스의 메서드, 속성 또는 초기화 메서드를 호출할 때 사용
- 부모 클래스의 메서드를 호출하거나 부모 클래스의 초기화 메서드를 호출하는 데 사용
- super.method() 또는 super.property와 같이 사용하여 부모 클래스의 기능을 호출
- final
- 클래스, 메서드, 속성 또는 서브스크립트를 표시하여 상속이 불가능하도록 만듭니다.
- final 키워드가 클래스에 사용되면 해당 클래스는 상속될 수 없다.
- 메서드, 속성, 서브스크립트에 사용될 경우, 해당 멤버들을 재정의(Override)할 수 없다.
// 부모 클래스(Person) 선언
class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
func greet() {
print("Hello, my name is \(name).")
}
}
// Person 클래스를 상속받는 자식 클래스(Student) 선언
class Student: Person {
var studentID: Int
init(name: String, age: Int, studentID: Int) {
self.studentID = studentID
super.init(name: name, age: age)
}
func study() {
print("\(name) is studying.")
}
}
// Student 클래스 인스턴스 생성 및 사용
let john = Student(name: "John", age: 20, studentID: 123)
john.greet() // 출력: Hello, my name is John.
john.study() // 출력: John is studying.
// override, super 키워드 예시
class Animal {
func makeSound() {
print("Some generic sound")
}
}
class Dog: Animal {
override func makeSound() {
super.makeSound() // 부모 클래스의 메서드 호출
print("Bark!")
}
}
let dog = Dog()
dog.makeSound()
// final 키워드 예시
final class Vehicle {
final var wheels: Int = 0
final func makeSound() {
print("Some generic sound")
}
}
// Error: 'SubVehicle' cannot inherit from final class 'Vehicle'
class SubVehicle: Vehicle {
// Error: 'wheels' cannot override 'final' var from superclass
// override var wheels: Int = 4
// Error: 'makeSound()' cannot override a final method
// override func makeSound() {
// print("Custom sound")
// }
}
#2. initializer (초기화)
- 초기화와 생성자
- 초기화는 클래스, 구조체, 또는 열거형의 인스턴스를 생성하고 속성을 초기화하여 사용할 수 있도록 하는 과정으로, 이 기능이 제공되는 것을 생성자(Constructor)라고 한다. 즉, 객체를 생성할 때 항상 실행되며, 맨 처음 실행되는 메소드를 의미한다.
→ 객체가 메모리에 할당되고 속성이 적절히 설정되어 안정적으로 사용될 수 있도록 하는 중요한 단계
※ 인스턴스란?
클래스, 구조체 또는 열거형과 같은 타입의 실제 예시
→ 클래스나 구조체 등의 템플릿(틀)을 기반으로 생성된 실제 데이터
( = 클래스나 구조체를 기반으로 만들어진 객체 )
// Person 클래스 정의
class Person {
var name: String
var age: Int
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 클래스의 인스턴스 생성
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.
★ 초기화 방법 ★
#1. 기본 초기화(Default Initialization)
- Swift는 클래스의 속성이 기본 값으로 초기화되도록 지원 → 클래스의 모든 속성이 기본 값을 가지고 있을 때 자동 발생
- 값과 타입이 모두 지정되어 있을 경우 별도의 초기화 작업을 해 주지 않아도 된다.
class Person {
var name: String = ""
var age: Int = 0
}
let person = Person() // 기본 초기화
#2. 지정 초기화(Designated Initialization)
- init 키워드를 사용하여 클래스의 모든 속성을 초기화하는 메서드
class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
let person = Person(name: "John", age: 30) // 지정 초기화
#3. 편의 초기화(Convenience Initialization)
- 기본 초기화 또는 지정 초기화를 간편하게 호출하는 보조 메서드
class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
convenience init(name: String) {
self.init(name: name, age: 0)
}
}
let person = Person(name: "Alice") // 편의 초기화 사용
#4. 강제 해제(Force Unwrapping)되지 않는 옵셔널 초기화
- 옵셔널 타입을 가진 속성은 선언과 동시에 초기화되거나 나중에 값을 할당할 수 있다.
class Person {
var name: String?
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) {
// 유효한 사용자 이름인지 확인
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") {
print("Valid username: \\(invalidProfile.username)")
} else {
print("Invalid username. Username should be at least 5 characters long.")
}
// struct의 실패 가능 생성자
struct Animal {
let name: String
init?(name: String) {
if name.isEmpty {
return nil // 생성자 내에서 실패 가능 부분에 nil을 리턴하면 됨
}
self.name = name
}
}
let animal1 = Animal(name: "choco") //인스턴스 생성. 타입은 Animal? 이다
let animal2 = Animal(name: "") // 문자열이기에 유효한 타입이지만 nil이 리턴된다
// enum의 실패 가능 생성자
enum HeightUnit {
case feet
case centiMeter
init?(symbol: String) {
switch symbol {
case "f":
self = HeightUnit.feet
case "cm":
self = HeightUnit.centiMeter
default:
return nil
}
}
}
let feet: HeightUnit = HeightUnit.feet // HeightUnit 타입
let centi: HeightUnit? = HeightUnit(symbol: "cm")
let feet2: HeightUnit? = HeightUnit(symbol: "F") // nil
'iOS 앱 개발자 프로젝트 > Swift 문법 정복하기' 카테고리의 다른 글
[Swift] Exception (throws, throw, do-catch, try) (0) | 2024.03.13 |
---|---|
[Swift] Property Observer, Type Casting, Access Modifier (0) | 2024.03.13 |
[Swift] Class, Struct, Enum (0) | 2024.03.11 |
[Swift] array, set, dictionary and OOP (1) | 2024.03.10 |
[Swift] queue & stack (0) | 2024.03.10 |