https://kotlinlang.org logo
Title
t

Travis Griggs

09/16/2021, 12:30 AM
I have a polymorphic class tree. I want to enumerate a list of leaf classes, and evaluate each one with an argument and let each one tell me how suited it is for that context. The sorting and selection is straightforward to me. It's how to get abstract class side methods and a list of class instances that is confounding me.
listOf<DragGesture>(DragCyclePositionGesture.class, DragMoveGesture.class, DragBeginGesture.class, DragEndGesture.class)
is not legal. Number one, there needs to be way a way to make the template not be instances of DragGesture, but rather subtypes of DragGesture? Is that even specifiable? And the compiler isn't happy after the first .class either, i start getting all kinds of red after that. Am I supposed to use companions in this case? I'm not even sure how companions fit in the scheme of inheritance. 😕
j

Joffrey

09/16/2021, 7:06 AM
First things first, Kotlin's way of referring to classes is
MyClass::class
(not
.class
). Now that being said, if you want to use inheritance so that the classes can tell you something polymorphically (not instances of those classes), then using companion objects seems appropriate because they can implement interfaces, unlike
KClass
or
Class
t

Travis Griggs

09/16/2021, 4:07 PM
The solution I came up with looks like:
val candidates = listOf(
   Pair(DragCyclePositionGesture::proximity, ::DragCyclePositionGesture),
   Pair(DragMoveGesture::proximity, ::DragMoveGesture),
   Pair(DragBeginGesture::proximity, ::DragBeginGesture),
   Pair(DragEndGesture::proximity, ::DragEndGesture)
)
val filtered = candidates.filter { it.first(this, event).abs <= tolerance }
return filtered.minByOrNull { it.first(this, event).abs }?.let { (_, constructor) ->
   val gesture = constructor()
   gesture.loadFrom(this)
   gesture
}
The part I'm not too hip on is the pairs of companion::function and constructor reference.
I would have rather seen
xxx.proximity(this, event)
in the filter and minBy blocks
j

Joffrey

09/16/2021, 5:26 PM
Instead of a pair like this you could use an interface like
GestureFactory<T : DragGesture>
and make the companion objects of each class implement it. It would define the proximity function and factory function in a nicer way I guess
So you would just have a list of companion objects instead of a list of pairs
t

Travis Griggs

09/16/2021, 9:44 PM
how does one make a list of companion objects?
j

Joffrey

09/17/2021, 12:51 AM
Just use
listOf(DragMoveGesture, DragBeginGesture)
(etc.)