1 class
- struct 처럼 property와 method를 포함하고 있다.
- struct와의 차이로 class는 heap영역에 생성되는 reference type이라고 했다.
- 따라서 동일한 객체를 가리킬 때는 class가 유용하지만 값이 동일한 두 객체를 같다고 판단해야 하는 경우는 struct가 더 유리하다.
- struct에서 class로의 변환은 쉬우니 일단 struct를 사용하고 필요에 따라 class로 전환하자.
- swift의 String, Array, Dictionary모두 struct로 되어있다.
struct PersonStruct {
var firstName: String
var lastName: String
var fullName: String {
return "\(firstName) \(lastName)"
}
mutating func uppercaseName() {
firstName = firstName.uppercased()
lastName = lastName.uppercased()
}
}
class PersonClass {
var firstName: String
var lastName: String
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
}
var fullName: String {
return "\(firstName) \(lastName)"
}
func uppercaseName() {
firstName = firstName.uppercased()
lastName = lastName.uppercased()
}
}
- struct와 달리 class는 반드시 생성자를 정의해줘야 한다.
- class에서는 mutating 키워드를 사용하지 않는다.
2 Inheritance
- swift에서 상속을 예제를 통해 바로 알아보자.
struct Grade {
var letter: Character
var points: Double
var credits: Double
}
class Person {
var firstName: String
var lastName: String
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
}
func printMyName() {
print("My name is \(firstName) \(lastName)")
}
}
class Student: Person {
var grades: [Grade] = []
}
let jay = Person(firstName: "Jay", lastName: "Lee")
let jason = Student(firstName: "Jasson", lastName: "Lee")
jay.firstName
jason.firstName
jay.printMyName()
jason.printMyName()
- Student는 Person을 상속받아 Person의 property와 method를 모두 사용할 수 있게 되었다.
- 그 밖의 student 자신을 특징짓는 grades라는 property를 추가로 지닐 수 있다.
- 다른 언어와 마찬가지로 sub class의 super class 다중 상속이 불가하며 상속의 깊이는 제약이 없다.
3 Override
class Student {
var firstName: String
var lastName: String
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
}
func printMyName() {
print("My name is \(firstName) \(lastName)")
}
}
// 학생인데 운동선수
class StudentAthlete: Student {
var minimumTrainingTime: Int = 2
var trainedTime: Int = 0
func train() {
trainedTime += 1
}
}
// 운동선인데 축구선수
class FootballPlayer: StudentAthlete {
var footballTeam = "FC Swift"
override func train() {
trainedTime += 2
}
}
// Person > Student > Athelete > Football Player
var athelete = FootballPlayer(firstName: "Heung", lastName: "Son")
athelete.train()
athelete.trainedTime
- FootballPlayer가 StudentAthlete을 상속하고 superclass의 train()함수를 재정의하여 사용하고 있다.
4 Upper Cast / Down Cast
athelete1 = athelete2 as StudentAthlete
- footballPlayer는 StudentAthlete을 상속받았으니 athelete1이 가리킬 수 있다.
- 하지만 athelete1으로는 footballPlayer만의 property를 접근할 수 없다.
- athelete1이 가리키고 있는 객체는 사실상 footballPlayer이기 때문에 이를 down cast해서 footballPlayer만의 property에 접근 할 수 있다.
if let son = athelete1 as? FootballPlayer {
print("--> team:\(son.footballTeam)")
}
- as?를 통해 son 변수에 athelete1을 옵셔녈 바인딩하고 성공했을 때 그 결과에 접근할 수 있다.
5 상속관계에서의 생성자 호출
- swift에서는 2 phase initialization을 거쳐 생성자가 호출되어 class 생성이 이루어진다.
*Phase 1
- phase 1 에서 모든 stored property는 initialize되어야 한다.
- Java와는 좀 다르게 sub class의 property를 set하고 나서 super class의 생성자를 호출한다.
class StudentAthlete: Student {
var minimumTrainingTime: Int = 2
var trainedTime: Int = 0
var sports: [String]
init(firstName: String, lastName: String, sports: [String]) {
// Phase 1
self.sports = sports
super.init(firstName: firstName, lastName: lastName)
}
}
*Phase 2
- phase 1이 완료되기 전까지는 property, method에 접근이 불가능하다.
- 따라서 부모 생성자 호출이 끝나는 시점 이후를 phase2라고 하고 이때부터 property, method에 대한 접근이 풀린다.
- 이 단계에서 property에 대한 접근, method 활용이 가능하다.
class StudentAthlete: Student {
var minimumTrainingTime: Int = 2
var trainedTime: Int = 0
var sports: [String]
init(firstName: String, lastName: String, sports: [String]) {
// Phase 1
self.sports = sports
super.init(firstName: firstName, lastName: lastName)
// Phase 2
self.train()
}
func train() {
trainedTime += 1
}
}
6 Designated initializer / Convenience initialize
- 이미 주 이니셜라이저가 있고 이것과 달리 모든 property를 초기화할 필요가 없을 때 처럼 간편하게 호출할 수 있는 initializer이다.
- convienience키워들 사용한다.
- 다양한 방식으로 Initializer를 정의해서 사용할 수 있다.
*designated initializer
- 주 이니셜라이저를 designated initializer라고 한다.
- 상속관계의 class에서 subclass의 DI는 super class의 DI를 반드시 호출해야한다.
*convenience initialize
- 간편한 방식으로 호출하고 싶어서 새롭게 정의한 initializer를 convenience initializer라고 한다.
- CI는 반드시 같은 class내의 이니셜라이저를 호출해야한다. 따라서 결국 CI는 궁극적으로 DI를 호출하게 된다.
import UIKit
struct Grade {
var letter: Character
var points: Double
var credits: Double
}
class Person {
var firstName: String
var lastName: String
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
}
func printMyName() {
print("My name is \(firstName) \(lastName)")
}
}
class Student: Person {
var grades: [Grade] = []
override init(firstName: String, lastName: String) {
super.init(firstName: firstName, lastName: lastName)
}
convenience init(student: Student) {
self.init(firstName: student.firstName, lastName: student.lastName)
}
}
// 학생인데 운동선수
class StudentAthlete: Student {
var minimumTrainingTime: Int = 2
var trainedTime: Int = 0
var sports: [String]
init(firstName: String, lastName: String, sports: [String]) {
// Phase 1
self.sports = sports
super.init(firstName: firstName, lastName: lastName)
// Phase 2
self.train()
}
convenience init(name: String) {
self.init(firstName: name, lastName: "", sports: [])
}
func train() {
trainedTime += 1
}
}
// 운동선인데 축구선수
class FootballPlayer: StudentAthlete {
var footballTeam = "FC Swift"
override func train() {
trainedTime += 2
}
}
let student1 = Student(firstName: "Jason", lastName: "Lee")
let student1_1 = Student(student: student1)
let student2 = StudentAthlete(firstName: "Jay", lastName: "Lee", sports: ["Football"])
let student3 = StudentAthlete(name: "Mike")
'ComputerScience > ios App(Storyboard)' 카테고리의 다른 글
ios - 13 Custom Cell (0) | 2021.07.28 |
---|---|
ios - 12 Table View, Table View Cell (0) | 2021.07.25 |
ios - 10 swift 기본문법(Structure) (0) | 2021.07.22 |
ios - 9 swift 기본문법 (Closure) (0) | 2021.07.21 |
ios - 8 swift 기본문법(Array, Dictionary, Set) (0) | 2021.07.21 |