TIL: 확장 가능 멤버 (속성과 메서드)

Royce·2025년 3월 23일

Swift 문법

목록 보기
42/63

멤버의 확장(계산 속성)

  • 확장을 사용하면 기존 타입에 새로운 기능을 추가할 수 있다
  • 특히 계산 속성(타입 계산 속성, 인스턴스 계산 속성)을 추가하여 값을 연산하여 반환할 수 있다

(타입) 계산 속성의 확장 (예시: String)

// String 타입에 타입 계산 속성 추가
extension String {
    static var defaultGreeting: String {
        return "Hello, Swift!"
    }
}

// 사용 예시
print(String.defaultGreeting)  // 출력: Hello, Swift!
  • String 타입에 새로운 타입 계산 속성 defaultGreeting을 추가하였다
  • 이 계산 속성은 항상 "Hello, Swift!" 라는 값을 반환한다
  • 타입 계산 속성이기 때문에 타입 자체에서 호출할 수 있다 (String.defaultGreeting)
  • 확장을 사용하면 기존 타입을 수정하지 않고도 새로운 기능을 추가할 수 있다

(인스턴스) 계산 속성의 확장 (예시: String)

// String 타입에 인스턴스 계산 속성 추가
extension String {
    var wordCount: Int {
        return self.split(separator: " ").count
    }
    
    var reversedString: String {
        return String(self.reversed())
    }
}

// 사용 예시
let myString = "Swift programming is fun"
print(myString.wordCount)      // 출력: 4
print(myString.reversedString)  // 출력: nuf si gnimmargorp tfiwS
  • String 타입에 두 가지 인스턴스 계산 속성 wordCountreversedString을 추가하였다
  • wordCount: 공백을 기준으로 문자열을 나누어 단어의 개수를 반환한다
  • reversedString: 문자열을 뒤집어서 반환한다
  • 계산 속성은 읽기 전용으로 정의되었으며, 값을 변경할 수는 없다
  • 기존의 String 인스턴스에서도 이 기능을 사용할 수 있다 (myString.wordCount, myString.reversedString)

(인스턴스) 계산 속성 확장의 장점 예시 (예시: Date)

import Foundation

// Date 타입에 인스턴스 계산 속성 추가
extension Date {
    var formatted: String {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        return formatter.string(from: self)
    }
    
    var dayOfWeek: String {
        let formatter = DateFormatter()
        formatter.dateFormat = "EEEE"
        return formatter.string(from: self)
    }
}

// 사용 예시
let now = Date()
print(now.formatted)   // 출력: 현재 날짜와 시간 (예: 2025-03-25 10:23:45)
print(now.dayOfWeek)    // 출력: 오늘의 요일 (예: Tuesday)
  • Date 타입에 두 가지 인스턴스 계산 속성을 추가하였다 (formatted, dayOfWeek)
  • formatted: 현재 날짜와 시간을 문자열로 반환한다 (포맷 지정 가능)
  • dayOfWeek: 현재 날짜의 요일을 반환한다 (예: Monday, Tuesday 등)
  • 기존의 Date 인스턴스에서도 이 기능을 사용할 수 있다 (now.formatted, now.dayOfWeek)
  • 확장을 사용하면 기존의 타입을 수정하지 않고도 매우 유용한 기능을 추가할 수 있다

(인스턴스) 계산 속성 확장의 장점 예시 (예시: Array)

// Array 타입에 인스턴스 계산 속성 추가 (Int 배열 전용)
extension Array where Element == Int {
    var sum: Int {
        return self.reduce(0, +)
    }
    
    var average: Double {
        return self.isEmpty ? 0.0 : Double(self.sum) / Double(self.count)
    }
}

// 사용 예시
let numbers = [10, 20, 30, 40, 50]
print(numbers.sum)     // 출력: 150
print(numbers.average)  // 출력: 30.0
  • Array 타입을 확장하여 Int 타입 배열에 새로운 계산 속성을 추가하였다
  • sum: 배열의 모든 요소를 더해서 반환한다
  • average: 배열의 평균값을 계산하여 반환한다
  • 기존의 Array 인스턴스에서도 이 기능을 사용할 수 있다 (numbers.sum, numbers.average)
  • 제네릭 확장을 활용하여 특정 타입(Int)의 배열에만 기능을 추가할 수 있다

요약

  • 확장을 사용하면 기존 타입을 수정하지 않고도 새로운 기능을 추가할 수 있다
  • 타입 계산 속성과 인스턴스 계산 속성을 추가하여 기능을 확장할 수 있다
  • 기존의 인스턴스에서도 확장에서 정의한 기능을 사용할 수 있다 (예: numbers.sum, myString.wordCount)
  • 확장은 코드의 가독성과 사용성을 크게 개선할 수 있다
  • 특정 타입(예: Int 배열)에만 기능을 추가할 수도 있다 (제네릭 확장)

멤버의 확장(메서드)

  • 확장을 사용하면 기존 타입에 새로운 메서드를 추가할 수 있다
  • 타입 메서드와 인스턴스 메서드 모두 확장을 통해 추가할 수 있다
  • 구조체나 열거형에서 자기 자신을 변경하는 메서드를 구현할 때는 mutating 키워드가 필요하다

(타입) 메서드의 확장 (예시: Double)

// Double 타입에 타입 메서드 추가하기
extension Double {
    
    /// 주어진 범위에서 랜덤한 Double 값을 반환하는 타입 메서드
    static func random(in range: ClosedRange<Double>) -> Double {
        let diff = range.upperBound - range.lowerBound
        let randomValue = Double(arc4random()) / Double(UInt32.max)
        return range.lowerBound + randomValue * diff
    }
    
    /// 두 Double 값 사이의 평균값을 반환하는 타입 메서드
    static func average(_ value1: Double, _ value2: Double) -> Double {
        return (value1 + value2) / 2
    }
}

// 사용 예시
let randomValue = Double.random(in: 1.0...10.0)
print("랜덤 값: \(randomValue)")  // 출력: 예) 랜덤 값: 7.234098

let averageValue = Double.average(5.0, 10.0)
print("평균 값: \(averageValue)")  // 출력: 평균 값: 7.5
  • Double 타입에 두 가지 타입 메서드를 추가하였다
    random(in:): 주어진 범위에서 랜덤한 Double 값을 반환한다
    average(_:_:): 두 개의 Double 값 사이의 평균값을 반환한다
  • 확장을 사용하여 기존 타입을 수정하지 않고 새로운 타입 메서드를 추가하였다
  • 타입 메서드이기 때문에 Double.random(in:) 또는 Double.average(_:_) 형식으로 호출한다

(인스턴스) 메서드의 확장 (예시: String)

// String 타입에 인스턴스 메서드 추가하기
extension String {
    
    /// 주어진 단어를 포함하고 있는지 확인하는 인스턴스 메서드
    func containsWord(_ word: String) -> Bool {
        return self.components(separatedBy: " ").contains(word)
    }
    
    /// 문자열을 주어진 횟수만큼 반복해서 출력하는 인스턴스 메서드
    func printRepeatedly(times: Int) {
        for _ in 0..<times {
            print(self)
        }
    }
}

// 사용 예시
let sentence = "Swift programming is fun"
print(sentence.containsWord("Swift"))   // 출력: true
print(sentence.containsWord("Python"))  // 출력: false

"Hello".printRepeatedly(times: 3)
// 출력:
// Hello
// Hello
// Hello
  • String 타입에 두 가지 인스턴스 메서드를 추가하였다
    containsWord(_:): 문자열에 특정 단어가 포함되어 있는지 확인한다
    printRepeatedly(times:): 문자열을 주어진 횟수만큼 출력한다
  • 인스턴스 메서드이기 때문에 기존의 String 인스턴스에서 호출할 수 있다 (sentence.containsWord("Swift"))
  • 확장을 통해 기능을 추가하므로 기존의 String 타입을 수정하지 않아도 된다

mutating 인스턴스 메서드의 확장 (예시: Array)

구조체나 열거형에서, 자신의 속성을 변경하는 메서드는 mutating 키워드가 필요하다

// Array 타입에 mutating 인스턴스 메서드 추가하기
extension Array where Element: Comparable {
    
    /// 배열의 요소를 오름차순으로 정렬하는 mutating 메서드
    mutating func sortAscending() {
        self = self.sorted()
    }
    
    /// 배열의 모든 요소를 두 배로 만드는 mutating 메서드 (Int 배열에만 적용)
    mutating func doubleValues() where Element == Int {
        self = self.map { $0 * 2 }
    }
}

// 사용 예시
var numbers = [5, 2, 9, 1, 7]
numbers.sortAscending()
print(numbers)  // 출력: [1, 2, 5, 7, 9]

var intNumbers = [1, 2, 3, 4, 5]
intNumbers.doubleValues()
print(intNumbers)  // 출력: [2, 4, 6, 8, 10]
  • Array 타입에 두 가지 mutating 인스턴스 메서드를 추가하였다
    sortAscending(): 배열의 요소를 오름차순으로 정렬한다 (self를 변경하므로 mutating 필요)
    doubleValues(): Int 타입의 배열에만 적용되며, 모든 값을 두 배로 만든다
  • mutating 키워드는 구조체와 열거형에서 자신을 변경할 수 있도록 허용한다
  • 확장을 사용하면 기존 타입의 메서드를 더욱 유용하게 만들 수 있다

요약

  • 확장을 사용하여 기존 타입에 새로운 타입 메서드 및 인스턴스 메서드를 추가할 수 있다
  • mutating 키워드를 사용하여 구조체나 열거형의 속성을 변경하는 메서드를 확장할 수 있다
  • 기존의 인스턴스에서도 확장에서 정의한 메서드를 사용할 수 있다
  • 확장은 기존 타입을 수정하지 않고도 기능을 추가할 수 있는 강력한 도구이다
profile
iOS 개발자 지망생

0개의 댓글