user9303491
user9303491

Reputation:

How to implement custom casting

I would like to implement custom conversion function of my class Foo to be able to pass it to the function that requres Bar object.

Equivalent C++ construction https://en.cppreference.com/w/cpp/language/cast_operator

class Foo {
    operator Bar () {...}
}

Upvotes: 3

Views: 2715

Answers (1)

Jayson Minard
Jayson Minard

Reputation: 85936

Kotlin does not have implicit conversions, as an intentional design decision. You would need to make it explicit. You can do this either putting the burden on the caller, or on the receiver.

For example, if I had:

class One() 
class Two()

object Utilities {
    fun foo(one: One) {
      ...
    }
}

If I want to pass an instance of Two to foo() I would either:

// add extension function for explicit conversion:
fun Two.toOne(): One { ... convert my instance to other type }

// now caller must convert:
Utilities.foo(myTwo.toOne())

The burden above is on the caller to convert, given this new extension function to do the conversion. This is typical of how Kotlin handles everything in the standard library.

But maybe you want to make it feel more implicit, so you could also add:

// add an extension to the callee, for implicit conversion:
fun Utilities.foo(two: Two) { foo(two.toOne()) }

// now caller doesn't have to convert:  
Utilities.foo(myTwo)

Now the caller never sees the conversion, although they have to import your extension function and their IDE hopefully will auto-suggest this for them. So it feels implicit but they had to choose to use that extension, which is easy to do.

Notice that none of the extension functions above needed any modifications to the actual classes. These extensions can be imported individually or in the whole package import. They can be done independently from classes you do or do not control. They can be done from anywhere at any time.

Final code, in its entirety:

// original classes

class One() 
class Two()

object Utilities {
    fun foo(one: One) {
      ...
    }
}

// extensions

fun Two.toOne(): One { 
   // ... convert my instance to other type 
}

fun Utilities.foo(two: Two) { foo(two.toOne()) }

And now you can use either model as your code style desires.

Upvotes: 4

Related Questions