본문 바로가기

Swift

Literal Initializer 만들기

최근 공부하다가 Literal이라는 것을 접하게 되었고

이 Literal이 Swift에서 어떻게 쓰이는 지 알고 적용해보고 싶었다!

Literal Initializer 만들기

Literal이란 소스코드의 어떤 값을 대표하는 것입니다.

예를 들어 0은 Integer, 0.0은 Floating-Point, "AAA"는 String과 같이 어떤 값이 주어지면 그 값을 대표하는 것이 Literal입니다.

이 Literal은 Swift에서 Protocol로 제공되고 있습니다.

 

Literal

Protocol

Integer ExpressibleByIntegerLiteral
Floating-Point ExpressibleByFloatLiteral
String ExpressibleByStringLiteral
Extended Grapheme Cluster ExpressibleByExtendedGraphemeClusterLiteral
Unicode Scalar ExpressibleByUnicodeScalarLiteral
Boolean ExpressibleByBooleanLiteral
Nil ExpressibleByNilLiteral
Array ExpressibleByArrayLiteral
Dictionary ExpressibleByDictionaryLiteral

모든 Protocol이 Expressible@@@Literal과 같은 모양을 하고 있군요..!

(이 Literal들은 모두 typealias로 @@@LiteralConvertible로도 제공되고 있습니다 🙂)

 

그렇다면 이 Literal이 어떻게 쓰이는 지 보도록 하겠습니다.

var number: Int = 5
type(of: number) // Int

 

number에 Int(5) 이렇게 변수 할당을 하지 않고 단순히 5만 넣어도 Int Type이란 것을 알 수 있습니다.

당연하다고 생각되지만 Int를 Tracking해보면

public struct Int : FixedWidthInteger, SignedInteger { ... }

public protocol SignedInteger : BinaryInteger, SignedNumeric { }

public protocol SignedNumeric : Numeric { ... }

public protocol Numeric : Equatable, ExpressibleByIntegerLiteral { ... } // *

 

Int Struct가 준수하고 있는 protocol을 쭉 올라가다보면 결국 Numeric이란 Protocol을 준수하고 있습니다.

(다른 UInt등 숫자와 관련된 struct모두 Numeric protocol을 준수하고 있습니다.)

 

Numeric Protocol은 어떤 Protocol을 준수하고 있는 지 보이시나요?

바로 ExpressibleByIntegerLiteral protocol을 준수하고 있습니다!

그래서 변수 할당을 할때 타입을 지정해주지 않아도 저 Literal에 따라 Int로 타입이 결정되는 것이죠.

(제 추측입니다...! 😅)

 

그렇다면 이 Literal을 이용해보겠습니다 ㅎㅎㅎ

 

먼저 아래와 같이 Person struct가 있다고 생각해봅시다.

struct Person {
  var height: Double
  
  init(height: Double) {
    self.height = height
  }
}

let person: Person = Person(height: 165.3)

 

person 변수에 Person을 할당할 때, Person initializer를 이용하여 할당했습니다.

그런데 이렇게 말고 아래와 같이 초기화하고 싶습니다.

let person: Person = 165.3

 

이렇게 초기화하기 위해선 ExpressibleByFloatLiteral을 이용해봅시다!

struct Person {
  var height: Double
  
  init(height: Double) {
    self.height = height
  }
}

extension Person: ExpressibleByFloatLiteral {
  init(floatLiteral value: FloatLiteralType) {
    self.init(height: value)
  }
}

let person: Person = 165.3

 

기존 Person struct를 extension하여 ExpressibleByFloatLiteral protocol을 준수하고

새로운 initializer를 만들어 제공하면 원하던 방식으로 초기화 할 수 있습니다! 👍

 

 

 

위와 같은 초기화 방법이 얼마나 많이 쓰일지 모르지만 그래도 새로운 지식도 얻고

흥미로운 protocol을 알게 되었습니다...! ㅎㅎ

나중에 이 Literal을 이용할 기회가 생긴다면 적극 이용해보겠습니다.. ㅎㅎ