본문 바로가기

ComputerScience/ios App(Storyboard)

ios - 11 swift 기본문법(Class)

728x90

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")

 

728x90
반응형