Hey! What is an equivalent of Swift's failable ini...
# announcements
s
Hey! What is an equivalent of Swift's failable initializer in Kotlin? Thanks! I have a Player and I want to init it with an asset, in case of not successful initialization I'd like player to be null, or at least throw.
z
Create a top-level function with the same name as your type (
Player
) that returns a
Player?
.
s
Failable initializers are definitely one of Swift’s, uh, “swift-ier” features lol - I would recommend maybe a
companion object
that defines
operator fun invoke(): Player?
or just a well-named factory method for this particular feature
s
thank you guys, I find them very useful in certain situations 🙂
so both of you suggest factory method right? 🙂
s
more or less
s
the companion object approach is more appealing to me
👍 1
Thanks guys!
h
I agree with the companion object approach. I like it so much that I've started tending towards things like this
Copy code
interface Player  {
    val name: String
    val verification: Verification?

    val isVerified get() = verification != null

    companion object {
         operator fun invoke(name: String, verification: Verification? = null): Player {
             if (verification != null && verification.isNotValid)
                 throw IllegalArgumentException("Cannot create player with name $name because provided verification is not valid.")

             return object : Player {
                 override val name = name
                 override val verification = verification
             }
         }
    }
}
This cheeky construction has the full functionality of a class, but can still be implemented freely. You can even achieve "multiple-inheritance" using delegation:
Copy code
class PlayerEntity(id: UUID, name: String, verification: Verification? = null) : Entity(id), Player by Player(name, verification)
z
The potential issue with that is that by not making it a data class, you lose the automatic implementation of
equals
,
hashcode
, and
copy
.
h
true, but you can't inherit from a data class anyhow 😮, so instead
PlayerEntity
can be the data class, if you fancy that. more to your point, with this approach, you can't override
equals
,
hashcode
, or
toString
at the interface level, so you'd want to have a basic implementation you always call in the event of multiple "constructors" (read: invoke), and add those
Any
functions there
i wasn't exhaustive in my testing, but from what i did, there was no performance impact. it's just very strange to read for folks that aren't kotlin-savvy
s
Thanks for the extras Casey! I haven't see the notification for the follow ups.
m
@Hullaballoonatic interesting use of interfaces and invoke. I'm not surprised there's no performance impact. I believe the compiler will create an anonymous class definition for you, and since you use the same 'class' everytime, it's effectively like you defining a concrete implementation of the interface. At least that's my understanding of what will get produced for that scenario. Just JVM, and not Kotlin specific.