새벽의 기록

[SOPT] 문법 스터디 #3 열거형과 프로퍼티 본문

SOPT/문법 스터디

[SOPT] 문법 스터디 #3 열거형과 프로퍼티

OneTen 2024. 11. 13. 13:30
열거형
    - enum의 연관 값 사용 방식
프로퍼티
    - 저장 프로퍼티, 계산 프로퍼티, 그리고 지연 프로퍼티의 차이점과 각각의 사용 예시
    - lazy  키워드
    - 프로퍼티 옵저버 - willSet과 didSet의 차이
    - static 키워드

 

열거형

열거형의 각 case에 동적으로 다른 값들을 추가로 지정할 수 있게 하는 값

→ 원시값과 달리, 각 case마다 다른 타입을 가질 수 있다

// 이름이 없고 타입만 있는
enum EnumName {
    case caseName(Type)              
    case caseName(Type, Type, ...)             
} 

// 이름도 있고 타입도 있는
enum EnumName {
    case caseName(name1: Type)              
    case caseName(name2: Type, name3: Type, ...)             
} 

연관값은 이렇게 case 옆에 튜플(지정되지 않은 데이터의 나열) 형태로 원하는 Type을 명시해서 사용

enum AppleProduct: String {
    case iPad = "5, 128GB"              
    case iPhone = "6, 64GB"           
    case macbook = "Pro, 256GB"            
} 

이렇게 case별로 RawValue를 정해주는 원시값을 사용할 수도 있지만, 모든 iPad5가 128GB이고, iPhone6가 64GB는 아님

→ 원시값은 모든 case가 동일한 형식(위에선 String)으로 RawValue를 가져야 하고, case 별 값은 미리 지정된 한 가지 값만 가질 수 있다는 단점이 있음

→ 그래서 이를 보완해서 사용할 수 있는 것이 연관값

enum AppleProduct {
    case iPad(model: String)              
    case iPhone(model: String, storage: Int)            
    case macbook(model: String, storage: Int, size: Int)             
} 

연관값 사용예시

enum MediaType {
    case book(title: String, author: String)
    case movie(title: String, director: String)
}

let favoriteBook = MediaType.book(title: "The Man Who Laughs", author: "Victor-Marie Hugo")
let favoriteMovie = MediaType.movie(title: "파묘", director: "장재현")

 

프로퍼티

1. 저장 프로퍼티, 계산 프로퍼티, 그리고 지연 프로퍼티의 차이점과 각각의 사용 예시

저장 프로퍼티

특정 클래스나 구조체의 인스턴스에 값을 저장하는 프로퍼티.

var로 선언된 저장 프로퍼티는 읽기 및 쓰기가 가능하며, let으로 선언된 경우 읽기 전용.

struct Person {
    var name: String    // 읽기, 쓰기 저장 프로퍼티
    let birthYear: Int  // 읽기 전용 저장 프로퍼티
}

let person = Person(name: "Kim", birthYear: 2000)
print(person.name) // "Kim"

계산 프로퍼티

값을 저장하지 않고, 특정 연산을 통해 값을 제공하는 프로퍼티.

get 블록과 set 블록을 사용하여 값을 가져오거나 설정할 수 있다.

struct Calculator {
    var x: Int
    var y: Int
    
    var result: Int {    // 계산 프로퍼티
        return x * y
    }
    
    var setting: Int {
        get {
            return 2 * (width + height)
        }
        set(newPerimeter) {
            let num = newPerimeter / 4
            x = num
            y = num
        }
    }
}

var calculator = Calculator(x: 10, y: 5)
print(calculator.result) // 50
print(calculator.setting) // 30

calculator.setting = 40
print(calculator.x) // 10
print(calculator.setting) // 100

지연 프로퍼티

처음 접근할 때까지 초기화되지 않는 프로퍼티.

계산 비용이 크거나 초기화 시점이 명확하지 않은 경우에 유용하다.

→ lazy 키워드를 사용해 선언하며, 반드시 var로 선언

class LazyEx {
    init() {
        print("DataLoader initialized")
    }
    
    func loadData() -> String {
        return "Data loaded"
    }
}

struct Test {
    // 지연 저장 프로퍼티로 선언
    lazy var lazyEx = LazyEx()
    
    func showData() {
        print(lazyEx.loadData()) // 이때 `lazyEx`가 초기화됨
    }
}

var test = Test()
test.showData()

// "DataLoader initialized"
// "Data loaded"

2. lazy 키워드

lazy 저장 변수는 이것이 처음 사용되기 전까지 초기값이 계산되지 않는 프로퍼티로, 항상 lazy 프로퍼티를 variable로 선언해야한다.

→ 왜냐하면 이 프로퍼트의 초기값을 인스턴스 초기화가 완료된 시점까지 알 수 없기 때문.

 

lazy 프로퍼티의 클로저 안에는 self를 사용할 수 있다. 

→ lazy 변수의 초기화에 사용되는 클로저에는 @non-escape가 자동적으로 적용된다. 따라서 외부에서 접근하는것이 아니므로 캡쳐를 할 필요가 없다.

 

상수 프로퍼티는 초기화가 끝나기전까지 반드시 값을 가져야하기 때문에, lazy로 선언될 수 없다.

 

3. 프로퍼티 옵저버 - willSet과 didSet의 차이

willSet 은 값이 변경되기 직전에 호출, didSet 은 값이 변경된 직후 호출

import Foundation

class Person {
    var name: String = "Anonymous" {
        willSet {
            print("실행되기 직전 이름: \\(name)")
        }
        didSet {
            print("실행 직후 이름: \\(name)")
        }
    }
}

let person = Person()
person.name = "Kim"
// 실행되기 직전 이름: Anonymous
// 실행 직후 이름: Kim

person.name = "Lee"
// 실행되기 직전 이름: Kim
// 실행 직후 이름: Lee

4. static 키워드

인스턴스 프로퍼티는 각 인스턴스에 고유한 값을 저장한다.

반면, 타입 프로퍼티는 타입 자체에 속하며 모든 인스턴스가 공유한다.

→ 이는 C의 static 상수나 변수와 유사하게, 모든 인스턴스에 공통된 값을 정의하는 데 유용하다.

 

Swift에서 타입 프로퍼티는 타입의 외부 중괄호 내에 타입의 정의 부분으로 작성되고 각 타입 프로퍼티는 지원되는 타입으로 명시적으로 범위가 지정된다.

Comments