TIL: 멤버의 확장(생성자)

Royce·2025년 3월 24일

Swift 문법

목록 보기
43/63

멤버의 확장(생성자)

  • 확장을 사용하여 기존 타입에 새로운 생성자를 추가할 수 있다
  • 구조체와 클래스에서 확장된 생성자를 정의하는 방식이 다르다

구조체와 클래스의 생성자 확장 차이

구조체 (Struct):

  • 구조체는 기본적으로 지정 생성자만 존재한다 (편의 생성자는 존재하지 않음)
  • 구조체는 상속과 관련이 없기 때문에 지정 생성자를 자유롭게 구현할 수 있다
  • 확장을 통해 편의 생성자와 비슷하게 본체의 지정 생성자를 호출하는 생성자도 구현할 수 있다
  • 기존의 기본 생성자와 멤버와이즈 생성자는 자동으로 제공된다
  • 하지만 본체에서 직접 지정 생성자를 구현하면 기본 생성자와 멤버와이즈 생성자는 제공되지 않는다
  • 예외적으로, 모든 저장 속성에 기본값을 제공하고, 본체에서 직접 생성자를 구현하지 않은 경우, 확장에서 정의한 생성자와 기존의 기본 생성자 및 멤버와이즈 생성자가 함께 제공된다

클래스 (Class):

  • 클래스는 확장에서 편의 생성자(convenience initializer)만 추가할 수 있다
  • 확장에서 지정 생성자를 정의할 수 없고, 소멸자도 추가할 수 없다
  • 편의 생성자는 기존 지정 생성자를 호출하는 방식으로 구현해야 한다
  • 기존의 지정 생성자와 확장에서 정의한 편의 생성자를 함께 사용할 수 있다

구조체 - 생성자 확장의 예시 (예시: Triangle)

// 구조체 정의
struct Triangle {
    var base: Double = 1.0    // 기본값 제공
    var height: Double = 1.0   // 기본값 제공
}

// 기본 생성자 사용 (구조체는 기본 생성자가 자동으로 제공됨)
let defaultTriangle = Triangle()  // 기본값으로 초기화된 삼각형


// 멤버와이즈 생성자 사용
let customTriangle = Triangle(base: 5.0, height: 3.0)


// 확장을 사용하여 새로운 생성자 추가하기
extension Triangle {
    
    /// 면적 값을 사용하여 밑변과 높이를 자동으로 계산하는 생성자
    init(area: Double) {
        let calculatedBase = (area * 2).squareRoot()
        let calculatedHeight = (area * 2).squareRoot()
        
        // 멤버와이즈 생성자 호출
        self.init(base: calculatedBase, height: calculatedHeight)
    }
    
    /// 동일한 크기의 삼각형을 복제하는 생성자
    init(copyFrom triangle: Triangle) {
        self.init(base: triangle.base, height: triangle.height)
    }
}

// 사용 예시
let areaTriangle = Triangle(area: 6.0)    // 면적 값을 사용하여 생성
let copyTriangle = Triangle(copyFrom: customTriangle)   // 기존 삼각형을 복제하여 생성

// 결과 출력
print("Area Triangle: Base = \(areaTriangle.base), Height = \(areaTriangle.height)")
print("Copy Triangle: Base = \(copyTriangle.base), Height = \(copyTriangle.height)")
  • Triangle 구조체는 baseheight 속성을 가진다
  • 기본값이 제공되므로 기본 생성자와 멤버와이즈 생성자가 자동으로 제공된다
  • 확장에서 두 가지 새로운 생성자를 추가하였다
    init(area:): 면적을 사용하여 밑변과 높이를 계산하여 초기화
    init(copyFrom:): 기존의 삼각형을 복제하여 새로운 인스턴스를 생성
  • 확장에서 멤버와이즈 생성자를 호출하는 방식으로 구현하였다 (self.init())
  • 확장에서 정의된 생성자와 기존의 기본 생성자 및 멤버와이즈 생성자를 모두 사용할 수 있다

클래스 - 생성자 확장의 예시 (예시: Person)

// 기존 클래스 정의
class Person {
    var name: String
    var age: Int
    
    // 지정 생성자
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

// 기존의 방식으로 인스턴스 생성
let person = Person(name: "Alice", age: 30)


// 확장을 사용하여 편의 생성자 추가하기
extension Person {
    
    /// 이름만 가지고 나이를 0으로 초기화하는 편의 생성자
    convenience init(name: String) {
        self.init(name: name, age: 0)
    }
    
    /// JSON 데이터로부터 인스턴스를 생성하는 편의 생성자 (가정)
    convenience init(json: [String: Any]) {
        let name = json["name"] as? String ?? "Unknown"
        let age = json["age"] as? Int ?? 0
        self.init(name: name, age: age)
    }
}

// 새로운 편의 생성자를 사용하여 인스턴스 생성
let personByName = Person(name: "Bob")
let personByJSON = Person(json: ["name": "Charlie", "age": 25])

// 결과 출력
print("Person 1 - Name: \(personByName.name), Age: \(personByName.age)")
print("Person 2 - Name: \(personByJSON.name), Age: \(personByJSON.age)")
  • Person 클래스는 이름과 나이를 가진다
  • 지정 생성자는 기존 방식으로 정의되었다
  • 확장에서 두 가지 편의 생성자를 추가하였다
    init(name:): 이름만 설정하여 나이를 0으로 초기화
    init(json:): JSON 데이터를 사용하여 인스턴스를 생성 (예: 서버로부터 받은 데이터)
  • 확장에서 추가된 생성자도 기존의 지정 생성자와 함께 사용할 수 있다

요약

  • 조체는 확장을 사용하여 지정 생성자도 추가할 수 있다 (본체에서 생성자를 정의하지 않은 경우)
  • 클래스는 확장에서 편의 생성자만 추가할 수 있다 (지정 생성자는 추가 불가능)
  • 확장에서 정의된 생성자는 기존의 기본 생성자 및 멤버와이즈 생성자와 함께 사용할 수 있다 (구조체)
  • 확장은 기존 타입을 수정하지 않고도 생성자를 추가할 수 있는 강력한 도구이다
profile
iOS 개발자 지망생

0개의 댓글