18

What is currently the best/preferred way to define explicit conversions in Swift? Of the top of my head I can think of two:

  • Creating custom initializers for the destination type via an extension, like this:

    extension String {
      init(_ myType: MyType) {
        self = "Some Value"
      }
    }
    

    This way, you could just use String(m) where m is of type MyType to convert m to a string.

  • Defining toType-Methods in the source type, like this:

    class MyType {
      func toString() -> String {
        return "Some Value"
      }
    }
    

    This is comparable to Swift's String.toInt(), which returns an Int?. But if this was the definitive way to go I would expect there to be protocols for the basic types for this, like an inversion of the already existing *LiteralConvertible protocols.

Sub-question: None of the two methods allow something like this to compile: let s: MyString = myTypeInstance (as String) (part in parentheses optional), but if I understand right, the as operator is only for downcasting within type hierarchies, is that correct?

Kolja
  • 1,197
  • 9
  • 17

1 Answers1

11

The pattern used in swift is the initializer. So for instance when converting an Int to UInt, we have to write:

var i: Int = 10
var u: UInt = UInt(i)

I would stick with that pattern.

As for the subquestion, the documentation states that:

Type casting is a way to check the type of an instance, and/or to treat that instance as if it is a different superclass or subclass from somewhere else in its own class hierarchy.

and

You can also use type casting to check whether a type conforms to a protocol

so no, the as keyword can`t be used to transform a value of a certain type to another type.

That can be tested in a simple way:

var i: Int = 10
var u: UInt = i as UInt

That generates an error:

'Int' is not convertible to 'UInt'

More about Type Casting

Antonio
  • 71,651
  • 11
  • 148
  • 165
  • OK, thanks. Also nice of you to include the documentation. I take it that providing extensions for built-in types for conversion is also the right thing to do? – Kolja Aug 30 '14 at 19:45
  • 1
    Yes, extensions is the tool in our hands when we are adding to 3rd party types. For our own code, it's just a matter of preference of course. In some cases using extensions can help keeping our code more organized and easier to browse. – Antonio Aug 30 '14 at 19:49
  • 1
    Thanks again. Now I just need implicit conversion for the few cases where it does make sense, but that I won't get from Swift. ;-) – Kolja Aug 30 '14 at 20:21
  • 4
    @Kolja: Actually you had gotten that in Swift, but they had a range of compiler problems and removed it early on. It used to be that you could define conversion functions (copy constructors in C++ parlance). To me, this is a hole in the language - the absence of this blocks a number of techniques. – Chris Conover May 08 '15 at 04:10
  • Actually this is still implemented somehow for NSNumber, which you can cast to numerous Swift primitives, i.e. `number as? Double` and `number as? Int` both succeed. – cutsoy Jan 15 '17 at 13:01
  • Yup, specially implemented in the runtime: https://github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/NSNumber.swift.gyb – Ammo Goettsch Feb 08 '17 at 01:14
  • Agh, so I can't implement a custom cast function (something like C#'s [`implicit operator`](https://learn.microsoft.com/en-us/dotnet/articles/csharp/language-reference/keywords/implicit)) in Swift? That's a shame... the implicit `Error` -> `NSError` bridge used when passing `Error`s to Objective-C code is broken and crashes for background services (at least when in a Framework, see http://stackoverflow.com/questions/43859552/swift-3-custom-urlprotocol-crashes-when-converting-error-to-nserror); calling my own `asNSError()` works but I was hoping to make it automatic. – CBHacking May 09 '17 at 18:33