Search code examples
swifttype-conversionprotocolsclass-extensions

Can you enforce type conversion in a protocol without defining a property/method?


I don't want to have to define asString.

protocol ConvertibleToString {var asString: String {get}}

extension Int: ConvertibleToString {
    var asString: String {return String(self)}
}

Solution

  • If I understand your question correctly – no, I don't think you can't define an "implicit" conversion that detects and uses a matching init from a specific type. The only way to convert from one type to another in Swift is to explicitly call an init for the "to" type that takes the "from" type, or a function or method on the "from" type that returns the "to" type. There's no way of implementing a protocol that says "use the init for this type with other type, if one is available".

    By the way, your ConvertibleToString protocol is essentially a version of Printable (with asString in place of description). So if what you want is to know if something is convertible to a string, you can just check for conformance to Printable. Though note one gotcha – String is not Printable. You can use toString(thing) to convert anything to a string, and it will use Printable where available (and do nothing to convert strings), though this does have the side-effect of giving you a default for non-printable types that you may not want depending on your need.

    Note you can require convertibility from something via a protocol:

    protocol ConvertibleFromInt {
        init(Int)
    }
    
    extension String: ConvertibleFromInt { }
    
    extension UInt64: ConvertibleFromInt { }
    
    func gimmeFromInt<T: ConvertibleFromInt>(i: Int) -> T {
        return T(i)
    }
    
    let s: String = gimmeFromInt(5)
    let ui: UInt64 = gimmeFromInt(5)