캡슐화
하는 인스턴스 메서드를 정의할 수 있습니다.class Counter {
var count = 0
func increment() {
count += 1
}
func increment(by amount: Int) {
count += amount
}
func reset() {
count = 0
}
}
let counter = Counter()
// the initial counter value is 0
counter.increment()
// the counter's value is now 1
counter.increment(by: 5)
// the counter's value is now 6
counter.reset()
// the counter's value is now 0
func increment() {
self.count += 1
}
struct Point {
var x = 0.0, y = 0.0
func isToTheRightOf(x: Double) -> Bool {
return self.x > x
}
}
let somePoint = Point(x: 4.0, y: 5.0)
if somePoint.isToTheRightOf(x: 1.0) {
print("This point is to the right of the line where x == 1.0")
}
// Prints "This point is to the right of the line where x == 1.0"
struct Point {
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveBy(x: 2.0, y: 3.0)
print("The point is now at (\(somePoint.x), \(somePoint.y))")
// Prints "The point is now at (3.0, 4.0)"
let fixedPoint = Point(x: 3.0, y: 3.0)
fixedPoint.moveBy(x: 2.0, y: 3.0)
// this will report an error
struct Point {
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
self = Point(x: x + deltaX, y: y + deltaY)
}
}
enum TriStateSwitch {
case off, low, high
mutating func next() {
switch self {
case .off:
self = .low
case .low:
self = .high
case .high:
self = .off
}
}
}
var ovenLight = TriStateSwitch.low
ovenLight.next()
// ovenLight is now equal to .high
ovenLight.next()
// ovenLight is now equal to .off
위에서 설명한 것처럼 인스턴스 메서드는 특정 유형의 인스턴스에서 호출하는 메서드입니다.
유형 자체에서 호출되는 메소드를 정의할 수도 있습니다. 이러한 종류의 메소드를 유형 메소드라고 합니다.
메소드의 func 키워드 앞에 static 키워드를 작성하여 유형 메소드를 나타냅니다.
class는 대신 class 키워드를 사용하여 하위 class가 해당 메서드의 상위 class 구현을 재정의할 수 있도록 할 수 있습니다.
Objective-C에서는 Objective-C class에 대해서만 유형 수준 메서드를 정의할 수 있습니다. Swift에서는 모든 class, struct 및 enum에 대한 유형 수준 메서드를 정의할 수 있습니다. 각 형식 메서드는 지원하는 형식으로 명시적으로 범위가 지정됩니다.
유형 메소드는 인스턴스 메소드와 같은 점 구문으로 호출됩니다. 그러나 해당 유형의 인스턴스가 아니라 유형에서 유형 메소드를 호출합니다.
SomeClass라는 class에서 유형 메서드를 호출하는 방법은 다음과 같습니다.
class SomeClass {
class func someTypeMethod() {
// type method implementation goes here
}
}
SomeClass.someTypeMethod()
형식 메서드의 본문 내에서 암시적 self 속성은 해당 형식의 인스턴스가 아니라 형식 자체를 참조
합니다.
즉, 인스턴스 속성 및 인스턴스 메서드 매개변수와 마찬가지로 self를 사용하여 형식 속성과 형식 메서드 매개변수를 구분할 수 있습니다.
보다 일반적으로 형식 메서드의 본문 내에서 사용하는 정규화되지 않은 메서드 및 속성 이름은 다른 형식 수준 메서드 및 속성을 참조합니다.
타입 메서드는 타입 이름을 접두사로 붙일 필요 없이 다른 메서드의 이름으로 다른 타입 메서드를 호출할 수 있습니다.
유사하게, struct 및 enum의 유형 메서드는 유형 이름 접두사 없이 유형 속성의 이름을 사용하여 유형 속성에 액세스할 수 있습니다.
아래 예는 게임의 여러 레벨 또는 단계를 통해 플레이어의 진행 상황을 추적하는 LevelTracker라는 struct를 정의합니다.
싱글 플레이어 게임이지만 단일 장치에 여러 플레이어의 정보를 저장할 수 있습니다.
게임을 처음 플레이할 때 게임의 모든 레벨(레벨 1 제외)이 잠겨 있습니다.
플레이어가 레벨을 완료할 때마다 장치의 모든 플레이어에 대해 해당 레벨이 잠금 해제됩니다.
LevelTracker struct는 유형 속성과 메서드를 사용하여 잠금 해제된 게임 레벨을 추적합니다.
또한 개별 플레이어의 현재 레벨을 추적합니다.
struct LevelTracker {
static var highestUnlockedLevel = 1
var currentLevel = 1
static func unlock(_ level: Int) {
if level > highestUnlockedLevel { highestUnlockedLevel = level }
}
static func isUnlocked(_ level: Int) -> Bool {
return level <= highestUnlockedLevel
}
@discardableResult
mutating func advance(to level: Int) -> Bool {
if LevelTracker.isUnlocked(level) {
currentLevel = level
return true
} else {
return false
}
}
}
LevelTracker struct는 모든 플레이어가 잠금 해제한 최고 레벨을 추적합니다.
이 값은 highUnlockedLevel이라는 유형 속성에 저장됩니다.
LevelTracker는 또한 highUnlockedLevel 속성과 함께 작동하는 두 가지 유형 함수를 정의합니다.
첫 번째는 새로운 레벨이 잠금 해제될 때마다 highUnlockedLevel의 값을 업데이트하는 unlock(_:)이라는 유형 함수입니다.
두 번째는 isUnlocked(_:)라는 편의 유형 함수로, 특정 레벨 번호가 이미 잠금 해제되어 있으면 true를 반환합니다.
(이러한 유형 메서드는 LevelTracker.highestUnlockedLevel로 작성할 필요 없이 highUnlockedLevel 유형 속성에 액세스할 수 있습니다.)
유형 속성 및 유형 메서드 외에도 LevelTracker는 게임을 통해 개별 플레이어의 진행 상황을 추적합니다.
currentLevel이라는 인스턴스 속성을 사용하여 플레이어가 현재 재생 중인 레벨을 추적합니다.
currentLevel 속성 관리를 돕기 위해 LevelTracker는 advance(to:)라는 인스턴스 메서드를 정의합니다.
currentLevel을 업데이트하기 전에 이 메서드는 요청된 새 수준이 이미 잠금 해제되어 있는지 확인합니다.
Advance(to:) 메서드는 부울 값을 반환하여 실제로 currentLevel을 설정할 수 있는지 여부를 나타냅니다.
Advance(to:) 메서드를 호출하는 코드가 반환 값을 무시하는 것은 반드시 실수가 아니기 때문에 이 함수는 @discardableResult 속성으로 표시됩니다.
LevelTracker struct는 아래와 같이 Player class와 함께 사용되어 개별 플레이어의 진행 상황을 추적하고 업데이트합니다.
class Player {
var tracker = LevelTracker()
let playerName: String
func complete(level: Int) {
LevelTracker.unlock(level + 1)
tracker.advance(to: level + 1)
}
init(name: String) {
playerName = name
}
}
Player class는 해당 플레이어의 진행 상황을 추적하기 위해 LevelTracker의 새 인스턴스를 만듭니다.
또한 플레이어가 특정 레벨을 완료할 때마다 호출되는 complete(level:) 메서드를 제공합니다.
이 방법은 모든 플레이어의 다음 레벨을 잠금 해제하고 플레이어의 진행 상황을 업데이트하여 다음 레벨로 이동합니다.
(advance(to:)의 부울 반환 값은 무시됩니다.
이전 줄에서 LevelTracker.unlock(_:) 호출에 의해 레벨이 잠금 해제된 것으로 알려져 있기 때문입니다.)
새 플레이어를 위한 Player class의 인스턴스를 만들고 플레이어가 레벨 1을 완료하면 어떻게 되는지 확인할 수 있습니다.
var player = Player(name: "Argyrios")
player.complete(level: 1)
print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
// Prints "highest unlocked level is now 2"
게임의 어떤 플레이어도 아직 잠금 해제하지 않은 레벨로 이동하려고 하는 두 번째 플레이어를 생성하면 플레이어의 현재 레벨 설정 시도가 실패합니다.
player = Player(name: "Beto")
if player.tracker.advance(to: 6) {
print("player is now on level 6")
} else {
print("level 6 hasn't yet been unlocked")
}
// Prints "level 6 hasn't yet been unlocked"