본문 바로가기

Apple/Swift

Swift 04 - 클래스(class)

반응형

class 프로퍼티와 메서드로 새로운 타입을 만들 수 있다는 점에서 구조체와 공통점이 있지만, 차이점이 있다.

첫번째 차이점은 memberwise initializer가 기본으로 제공되지 않는다는 점이다. 이것은 class에 프로퍼티가 있는 경우 꼭 자체 initializer를 함께 작성해야 한다는 점이다.

class ManchesterCityPlayers {
    var playerName: String
    var playerNubmer: Int

    init(playerName: String, playerNubmer: Int) {
        self.playerName = playerName
        self.playerNubmer = playerNubmer
    }
}

// 나머지는 struct와 같다.
let manCityPlayers = ManchesterCityPlayers(playerName: "kdb", playerNubmer: 17)
print(manCityPlayers.playerName)
print(manCityPlayers.playerNubmer)

// output
// kdb
// 17

 

struct와 가장큰 차이점 중 하나는 상속(inheritance)이 가능하다는 점이다. 상속은 기존에 생성한 class를 기반으로 다른 class를 만들 수 있다는 것이다. subclassing이라고도하고 상위 class를 parent(부모) class, super class라고 하고 , 하위 class를 child(자식) class 라고 부른다.

// 부모클래스, 슈퍼클래스 생성
class EplPlayers {
    var teamName: String
    var playerName: String
    var backNumber: Int
    
    init(teamName: String, playerName: String, backNumber: Int) {
        self.teamName = teamName
        self.playerName = playerName
        self.backNumber = backNumber
    }
}

// 자식클래스 생성
class ArsnalPlayers: EplPlayers {
    // teamName에 Arsnal을 기본으로 입력하고, Arsnal initializer가 EplPlayers initializer를 직접호출하므로써 모든 세팅이 동일하게 이뤄짐
    init(playerName: String, playerNumber: Int, isPlayerFromEngland: Bool) {
        super.init(teamName: "Arsnal", playerName: playerName, backNumber: playerNumber)
    }
}

swift에서는 안전한 코드 작성을 위해 자식 클래스에서 super.iniit()을 호출하도록 한다. 

 

child class는 parent class의 method를 자체적으로 바꿀 수 있고 이를 overriding(오버라이딩)이라고 한다. 아래 코드를 보면 Sonny 클래스가 SoccerPlayer 클래스를 상속받았기 때문에 SoccerPlayer 클래스의 shoot 메서드를 사용할 수 있는 것을 볼 수 있다.

class SoccerPlayer {
    func shoot() {
        print("shoooooot!!!")
    }
}

class Sonny: SoccerPlayer {
    
}

let sonny = Sonny()
sonny.shoot()

//output
// shoooooot!!!

여기서 메서드 오버라이딩을 통해서 Sonny 클래스에 대한 shoot 메서드를 변경할 수 있다. 메서드 오버라이딩을 위해서는 func 키워드 앞에 override 키워드를 작성하면 된다.

class SoccerPlayer {
    func shoot() {
        print("shoooooot!!!")
    }
}

class Sonny: SoccerPlayer {
    // override 키워드를 통해 매서드를 변경
    override func shoot() {
        print("powerful shoooooot!!!")
    }
}

let sonny = Sonny()
sonny.shoot()

// output
// powerful shoooooot!!!

클래스 상속은 매우 자주 사용하지만 final 키워드를 class 앞에 작성하면 해당 클래스를 상속할 수 없게 됩니다. final class는 다양한 목적으로 사용하게 된다.

final class BallondorPlayer {
    var playerName: String
    var backNumber: Int
    var teamName: String
    
    init(playerName: String, backNumber: Int, teamName: String) {
        self.playerName = playerName
        self.backNumber = backNumber
        self.teamName = teamName
    }
}

 

class 와 struct의 또 다른 차이점 중 하나는 복제 방법이다. struct를 복제할 때는 원본과 사본은 완전히 다르다. 둘 중 하나를 변경해도 다른 것은 변경되지 않는다. 클래스를 복제할 때는 원본과 사본 모두 같은 것을 가리키기 때문에 하나를 수정하면 다른 것도 변경된다. 

class WeaklyBestPlayer {
    var playerName: String = "Sonny"
}

var player = WeaklyBestPlayer()
print(player.playerName)

var anotherPlayer = player
print(anotherPlayer.playerName)
anotherPlayer.playerName = "winks"
print(player.playerName)
print(anotherPlayer.playerName)

//output
// Sonny
// Sonny
// winks
// winks

 

또 다른 차이점은 Deinitializer(소멸자)를 가질 수 있다는 것이다. 소멸자는 클래스의 인스턴스가 소멸될 때 실행되는 코드이다. initializer 가 init 키워드로 작성했다면, deinitializer는 deinit 키워드로 작성한다. deinit 키워드는 init 과 다르게 괄호를 사용하지 않는다.

class Player {
    var playerName: String = "Alan Shearer"
    
    init() {
        print("\(playerName)는 1988년에 사우스햄튼에서 데뷔하였다.")
    }
    
    func playerHistory() {
        print("\(playerName)는 이후에 260골을 넣었다")
    }
    
    deinit {
        print("\(playerName)는 2006년에 뉴캐슬에서 은퇴하였다.")
    }
}

for _ in 1...2 {
    let shearer = Player()
    shearer.playerHistory()
}

// output
Alan Shearer는 1988년에 사우스햄튼에서 데뷔하였다.
Alan Shearer는 이후에 260골을 넣었다
Alan Shearer는 2006년에 뉴캐슬에서 은퇴하였다.
Alan Shearer는 1988년에 사우스햄튼에서 데뷔하였다.
Alan Shearer는 이후에 260골을 넣었다
Alan Shearer는 2006년에 뉴캐슬에서 은퇴하였다.

 

마지막 차이점은 상수를 다루는 방법이다. 구조체는 구조체 자체가 상수이기 때문에 프로퍼티를 변경할 수 없지만, 변수(var) 프로퍼티를 가진 클래스는 해당 프로퍼티를 변경할 수 있다. 이런 이유로 클래스는 프로퍼티를 변경하는 메서드를 사용하지 않는다. 물론 안바꾸고 싶다면 let으로 프로퍼티를 선언하면 된다.

class Player {
	// var 프로퍼티를 가지고 있다면?
    var playerName = "Sonny"
}

let sonny = Player()
sonny.playerName = "harry kane" // 바로 바꿀 수 있다.
print(sonny.playerName)

// output
// harry kane
반응형

'Apple > Swift' 카테고리의 다른 글

Swift 06 - 익스텐션(extension)  (0) 2022.03.12
Swift 05 - 프로토콜(Protocol)  (0) 2022.03.12
Swift 03 - 구조체(struct)  (0) 2022.03.12
Swift 02 - 클로저(Closure)  (0) 2022.03.12
Swift 01 - 함수(function)  (0) 2022.03.11