Vakas
Vakas

Reputation: 6462

Literal Convertibles in Swift

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.

Upvotes: 1

Views: 1645

Answers (2)

Code Different
Code Different

Reputation: 93181

  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.

Upvotes: 2

Rizwan Mehboob
Rizwan Mehboob

Reputation: 1373

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

Upvotes: 0

Related Questions