Skip to content

Latest commit

 

History

History
117 lines (93 loc) · 4.93 KB

ExpressibleBy~~Literal.md

File metadata and controls

117 lines (93 loc) · 4.93 KB

ExpressibleBy~~Literal

  • 우리는 지금까지 10Int, "Hi"String이라고 당연하게 인지하고 있었음.
  • 하지만 IntString 모두 생성자를 가지는 구조체이기 때문에, 10원래 Int(10) 으로 선언되어야 하고, "Hi"String("Hi") 로 선언되어야 함.
  • 이렇게, 생성자를 사용하지 않고도 생성할 수 있게 만드는 것리터럴 (Literal) 이라고 함. 직역하면 '문자 그대로'라는 뜻
let number = 10
let string = "Hi"
let array = ["a", "b", "c"]
let dictionary = [
  "key1": "value1",
  "key2": "value2",
]
  • 이 리터럴을 가능하게 해주는 프로토콜이 있음 -> ExpressibleBy~~Literal

    따라서 IntExpressibleByIntegerLiteral을, StringExpressibleByStringLiteral을, ArrayExpressibleByArrayLiteral을, DictionaryExpressibleByDictionaryLiteral 프로토콜을 따르고 있음. 각 프로토콜은 리터럴 값을 받는 생성자를 정의.

  • 예를 들어 String에서 URL 을 변환하기 위해서는 아래와 같은 URL 생성자를 사용해야함

func getURL() -> URL
    return URL(string: "https://swiftrocks.com")!
}
  • 그러나 이 이니셜라이저를 매번 사용해야 하는 것을 방지하기 위해 ExpressibleByStringLiteral 을 사용하여 URL 문자열에서 직접 URL을 나타낼 수 있음
extension URL: ExpressibleByStringLiteral {
    public init(extendedGraphemeClusterLiteral value: String) {
        self = URL(string: value)!
    }

    public init(stringLiteral value: String) {
        self = URL(string: value)!
    }
}
  • 이를 통해 문자열 토큰만 사용하여 URL을 생성 하도록 리팩토링 가능
func getURL() -> URL
    return "https://swiftrocks.com"
}
  • 다른 예시로는 아래와 같이 ExpressibleByStringLiteral 을 conform 한 후 String 할당을 통해 Person 을 초기화 할 수 있음

    //전
    struct Person {
        let name: String
    }
    
    let ana = Person(name: "Ana")
    
    //후
    struct Person: ExpressibleByStringLiteral {
        init(stringLiteral value: String) {
            name = value
        }
        let name: String
    }
    
    let ana: Person = "Ana"

    ExpressibleByArrayLiteral 을 이용한 예시는 아래와 같음

    // 전
    extension Stack {
        init(from array: [T]) {
            array.forEach {
                push($0)
            }
        }
    }
    var stack = Stack(from: [1, 2, 3, 4])
    
    // 후
    extension Stack: ExpressibleByArrayLiteral {
        init(arrayLiteral elements: T...) {
            self.init(from: elements)
        }
    }
    
    var stack: Stack = [1, 2, 3, 4]
  • 표준 라이브러리에는 아래와 같은 ExpressibleBy 프로토콜이 포함되어 있음

    • Collection Literals
      • ExpressibleByArrayLiteral: [1,2,3] 같은 배열으로 표현 가능
      • ExpressibleByDictionaryLiteral: ["name": "SwiftRocks"] 같은 dictionary 로 표현 가능
    • Value Literals
      • ExpressibleByNilLiteral: nil 로 표현 가능
      • ExpressibleByIntegerLiteral: 10 같은 숫자로 표현 가능
      • ExpressibleByFloatLiteral: 2.5 같은 부동 소수점으로 표현 가능
      • ExpressibleByBooleanLiteral: true/false 같은 boolean 으로 표현 가능
    • String Literals
      • ExpressibleByStringLiteral: "Hello world" 와 같은 문자열으로 표현 가능
      • ExpressibleByUnicodeScalarLiteral: 단일 유니코드 스칼라 값으로 표현 가능. 이것의 사용 예는 CharacterString
      • ExpressibleByExtendedGraphemeClusterLiteral: UnicodeScalar와 유사하지만 단일 스칼라 대신 스칼라 체인 (a grapheme cluster)으로 구성. 즉, 사용자에게는 단일 문자로 인식되는 하나 이상의 Unicode scalar 값의 그룹. "é", "김" "🇮🇳" 와 같은 많은 개별 문자는 여러 유니코드 스칼라 값으로 구성될 수 있음. 이러한 코드 포인트는 유니코드의 boundary algorithms 에 의해 ExtendedGraphemeCluster로 결합됨
      • ExpressibleByStringInterpolation : "One cookie: $\(price), \(number) cookies: $\(price * number)." 와 같이 string interpolation 으로 표현 가능

출처