CLOVIS
05/22/2023, 8:02 PMis
check on all platforms? Is there some hidden cost, or is it safe to use in performance-sensitive applications?ephemient
05/22/2023, 8:10 PMis
checks is typically slower than using the JVM's built-in virtual dispatchCasey Brooks
05/22/2023, 8:10 PMis
(instanceof
in Java) operator was one of the biggest contributors to performance issues. It’s probably worse in old Java apps which had deep class hierarchies, but not quite as terribly expensive in the typical Kotlin appephemient
05/22/2023, 8:10 PMephemient
05/22/2023, 8:11 PMinstanceof Class
is probably faster than instanceof Interface
because the former only needs to scan the linear superclass hierarchy whereas superinterfaces form a treeCasey Brooks
05/22/2023, 8:11 PMephemient
05/22/2023, 8:12 PMCLOVIS
05/22/2023, 8:22 PMobject
implementations, expecting the user to combine them via interface delegation. However, one of the downside of interface delegation is that an implementation's methods cannot be overridden by the final object (since it's delegation, not overriding):
interface A {
fun a()
]
interface B {
fun b()
}
object FooDefault : A, B {
override fun a() = println("FooDefault.a")
override fun b() = println("FooDefault.b")
}
object Custom : A, B by FooDefault {
override fun a() = println("Custom.a")
}
Custom.b()
Output:
println("FooDefault.b")
println("FooDefault.a")
Whereas I would like to see
println("FooDefault.b")
println("Custom.a")
Instead, I thought of letting the caller know which implementation it was called on, and having each implementation call other methods as (implementation as? A) ?: this
Casey Brooks
05/22/2023, 8:31 PMCLOVIS
05/22/2023, 8:32 PMFooDefault.b
calls a()
.CLOVIS
05/22/2023, 8:33 PMephemient
05/22/2023, 8:33 PMinterface FooDefault : A, B
class Custom : FooDefault
Casey Brooks
05/22/2023, 8:38 PMCLOVIS
05/22/2023, 8:38 PMCLOVIS
05/22/2023, 8:41 PMA
and B
, so it's not feasible to implement them in a single object. However, if I use delegation to implement them separately, they can't call each other…Casey Brooks
05/22/2023, 8:42 PMCLOVIS
05/22/2023, 8:47 PMFor this case, since A and B are clearly related in some way, you might just want to move them into the same interface, so it’s clear that the two are able to talk to each other.It's true that this would make everything simpler, however in the real case there are dozens of sub-interfaces which all have 1--20 methods, so moving everything in a super-interface is not great 😕 As you can see, the main issue in this example is that
DefaultB
needs an instance of A
. The problem is, this dependency is specific to DefaultB
, not to all implementations of B
(otherwise, I would have had B : A
to make it explicit). So DefaultB
must allow the end-user (who defines the Custom
object) to control which instance of A
is used, otherwise the end-user can never override A.a
.Casey Brooks
05/22/2023, 8:51 PMCLOVIS
05/22/2023, 8:52 PMCasey Brooks
05/22/2023, 8:57 PM