1

I want to know how Literal Convertibles work in Swift. The little I know is that the fact that, in var myInteger = 5, myInteger magically becomes an Int is because Int adopts a protocol, ExpressibleByIntegerLiteral and we don't have to do var myInteger = Int(5). Similarly String, Array, Dictionary etc all conform to some Literal protocols. My Question is

  1. Am I right in my little understanding of Literal Convertibles?
  2. How can we implement these in our own types. For example

 class Employee {
    var name: String
    var salary: Int
    // rest of class functionality ...
}

How can I implement Literal Protocols to do var employee :Employee = "John Doe" which will automatically assign "John Doe" to employee's name property.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Vakas
  • 6,291
  • 3
  • 35
  • 47
  • 5
    Example for ExpressibleByStringLiteral (duplicate?): http://stackoverflow.com/questions/40373776/swift-struct-initialization-making-another-struct-like-string. For ExpressibleByIntegerLiteral: http://stackoverflow.com/questions/39160889/may-i-create-an-instance-of-a-structure-using-a-simple-int. A possible application: https://oleb.net/blog/2017/01/fun-with-string-interpolation/. – Martin R May 17 '17 at 15:04
  • 2
    Please, don't abuse literals for initializing custom classes. – Sulthan May 17 '17 at 15:05
  • Possible duplicate of [Swift struct initialization, making another struct like String](http://stackoverflow.com/questions/40373776/swift-struct-initialization-making-another-struct-like-string) – D4ttatraya May 17 '17 at 15:29
  • 1
    I would definitely avoid this. Making a `myInteger` from an integer literal makes sense. Making a `MyCustomSortedDictionary` from a Dictionary literal makes sense. Making an `Employee` from a String literal... does not. – Alexander May 17 '17 at 15:41

2 Answers2

2
  1. You are partially correct in your understanding of the various ExpressibleBy...Literal protocols. When the Swift compiler parses your source code into an Abstract Syntax Tree, it already identified what literal represents what data type: 5 is a literal of type Int, ["name": "John"] is a literal of type Dictionary, etc. Apple makes the base type conform to these protocols for the sake of completeness.
  2. You can adopt these protocols to give your class an opportunity to be initialized from a compile-time constant. But the use case is pretty narrow and I don't see how it applies to your particular situation.

For example, if you want to make your class conform to ExpressibleByStringLiteral, add an initializer to set all your properties from a String:

class Employee: ExpressibleByStringLiteral {
    typealias StringLiteralType = String

    var name: String
    var salary: Int

    required init(stringLiteral value: StringLiteralType) {
        let components = value.components(separatedBy: "|")
        self.name = components[0]
        self.salary = Int(components[1])!
    }
}

Then you can init your class like this:

let employee1: Employee = "John Smith|50000"

But if you dream about about writing something like this, it's not allowed:

let str = "Jane Doe|60000"
let employee2: Employee = str // error

And if you pass in the wrong data type for salary, it will be a run time error instead of a compile-time error:

let employee3: Employee = "Michael Davis|x" // you won't know this until you run the app

TL, DR: it is a very bad idea to abuse these ExpressibleBy...Literal types.

Code Different
  • 90,614
  • 16
  • 144
  • 163
0

This can be a scenario to work with Convertibles in custom types.

 struct Employee : ExpressibleByStringLiteral {
        var name: String = ""
        init() {}
        init(stringLiteral name: String) {
            self.name = name
        }
    }

    func reportName(_ employee: Employee) {
        print("Name of employee is \(employee.name)")
    }
    reportName("John Doe") //Name of employee is John Doe
Rizwan Mehboob
  • 1,333
  • 17
  • 19