야곰의 스위프트 프로그래밍 - 객체지향 프로그래밍과 스위프트

객체지향 프로그래밍과 스위프트

구조체와 클래스

구조체를 사용해야 하나? 클래스를 사용해야 하나?

다음의 조건 중 하나 이상에 해당된다면 구조체를 사용하는 것을 권장한다.

  • 연관된 간단한 값의 집합을 캡슐화하는 것만이 목적일 때
  • 캡슐화한 값을 참조하는 것보다 복사하는 것이 합당할 때
  • 구조체에 저장된 프로퍼티가 값 타입이며 참조하는 것보다 복사하는 것이 합당할 때
  • 다른 타입으로부터 상속받거나 자신을 상속할 필요가 없을 때

프로퍼티와 메소드

지연 저장 프로퍼티

  • 지연 저장 프로퍼티lazy stored property는 호출이 있어야 값을 초기화하며, 주로 복잡한 클래스나 구조체를 구현할 때 많이 사용된다.
    • 다중 스레드 환경에서 지연 저장 프로퍼티에 동시다발적으로 접근할 때 한 번만 초기화된다는 보장이 없다.

키 경로

  • 키 경로keyPath를 활용하여 어떤 프로퍼티의 위치만 참조할 수 있도록 할 수 있다. 키 경로를 사용하여 간접적으로 특정 타입의 어떤 프로퍼티 값을 가리켜야 할지 미리 지정해두고 사용할 수 있다.
  • 각 인스턴스의 KeyPath 서브스크립트 메소드에 키 경로를 전달하여 프로퍼티에 접근할 수 있다.
  • 키 경로를 잘 활용하면 타입 간의 의존성을 낮추는 데 많은 도움을 준다.
  • 키 경로는 타입 외부로 공개된 인스턴스 프로퍼티에 한하여 표현할 수 있다.
class Person {
var name: String
init(name: String) {
self.name = name
}
}
let person = Person(name: "presto")
let keyPath = \Person.name
person[keyPath: keyPath] // Presto

self 프로퍼티

  • 인스턴스 메소드에서는 self가 인스턴스를 가리키지만, 타입 메소드에서는 self가 타입 그 자체를 가리킨다.
  • self 프로퍼티를 활용하여 값 타입 인스턴스 자체의 값을 치환할 수 있다.
    • 클래스의 인스턴스는 참조 타입이므로 self 프로퍼티에 다른 참조를 할당할 수 없다.
struct Level {
var level: Int = 0
mutating func levelUp() {
level += 1
}
mutating func reset() {
self = Level()
}
}

타입 메소드

static 키워드를 사용하여 상속 후 메소드 재정의가 불가능한 타입 메소드를 정의할 수 있음

class 키워드를 사용하여 상속 후 메소드 재정의가 가능한 타입 메소드를 정의할 수 있음

접근 제어

설정자만 더 낮은 접근 수준을 갖도록 제한할 수 있다.

public struct SomeType {
// 저장 프로퍼티의 접근 수준 다르게 하기. 설정자는 비공개 접근수준, 접근자는 공개 접근수준.
public private(set) var property: Int = 0
// 서브스크립트의 접근 수준 다르게 하기. 설정자는 내부 접근수준, 접근자는 공개 접근수준.
public internal(set) subscript(some: Int) -> Int {
get { return property }
set { property += some }
}
// 저장 프로퍼티도 같은 방법으로 구현할 수 있다.
}