Emilio
09/11/2019, 7:26 PMwhen
. So I have something like (class internals omitted)
sealed class Node
sealed class SourceNode : Node() // No parents
sealed class SinkNode : Node() // No children
sealed class OpNode : Node()
// classes that extend the sealed classes here
I would like to distinguish at the type level nodes that have parents and nodes that have children so I could write something like:
fun foo(x: ParentNode): ParentNode {
// Do something to only parent nodes, possibly exhaustively match on them, and return a ParentNode
}
Where ParentNode
is somehow a subtype of Node
The problem is OpNode
is both a parent node and a child node which calls for multiple inheritance via interfaces, but I would like to be within the land of sealed classes for exhaustive matching. Is there a solution to this in kotlin?bbaldino
09/12/2019, 4:31 AMinterface Parent {
fun getChildren(): List<Node>
}
interface Child {
fun getParent(): Node
}
sealed class Node
class SourceNode : Node()
class SinkNode : Node()
class OpNode : Node(), Parent, Child {
override fun getChildren(): List<Node> {
TODO()
}
override fun getParent(): Node {
TODO()
}
}
Emilio
09/12/2019, 8:10 PMParent
and Child
treating them as nodes, without the run-time casting to Node
. For instance, being able to define the interfaces like:
interface Parent {
fun getChildren(): List<Child>
}
fun ConsumeParent(x: Parent) {
// Access some node specific fields of x without casting
val children = x.getChildren()
}
bbaldino
09/12/2019, 8:11 PMEmilio
09/12/2019, 9:14 PMinterface INode
then I lose exhaustive when
matching on Nodes, which would be nice to keep.bbaldino
09/12/2019, 9:14 PMEmilio
09/12/2019, 10:43 PMinterface INode {
val type : String
}
interface IParentNode : INode {
val children : List<IChildNode>
fun addChild(child: IChildNode)
}
interface IChildNode : INode
interface IAddNode : IParentNode, IChildNode {
val parent0 : IParentNode
val parent1 : IParentNode
}
sealed class Node
sealed class SourceNode : Node(), IParentNode
sealed class SinkNode : Node(), IChildNode
sealed class OpNode : Node(), IParentNode, IChildNode
class InputNode : SourceNode() {
override val type = "Input"
override val children: List<IChildNode>
get() = TODO()
override fun addChild(child: IChildNode) {
TODO()
}
}
class OutputNode : SinkNode() {
override val type: String = "Output"
}
class AddNode : OpNode(), IAddNode {
override val parent0: IParentNode
get() = TODO()
override val parent1: IParentNode
get() = TODO()
override val type: String = "+"
override val children: List<IChildNode>
get() = TODO()
override fun addChild(child: IChildNode) {
TODO()
}
}
fun foo(x: List<Node>) {
x.map { when(it) {
// TODO
}.let { } }
}
// Got from a Parent Nodes Children
fun bar(x: List<IChildNode>) {
foo(x) // will have to do an unchecked cast
}
Since IChildNode isn't in the sealed class of Node, I will have to litter unchecked casts in many places.bbaldino
09/12/2019, 10:46 PMEmilio
09/12/2019, 10:48 PMbbaldino
09/12/2019, 10:49 PMOpNode
sealed class ChildNode : Node(), IChildNode
sealed class ParentNode : Node(), IParentNode
sealed class ParentChildNode : Node(), IChildNode, IParentNode
sealed class SourceNode : ParentNode()
sealed class SinkNode : ChildNode()
sealed class OpNode : ParentChildNode()
Emilio
09/12/2019, 10:54 PMParentNode
(functions are covariant in return type), how would I type this function now that ParentChildNode
isn't a subtype of ParentNode
?bbaldino
09/12/2019, 10:55 PMConsumerNode
and DemuxerNode
but don't need to manipulate them much after they're created, so didn't need the generic typing reallyEmilio
09/12/2019, 11:03 PMNode
bbaldino
09/12/2019, 11:03 PMEmilio
09/12/2019, 11:12 PMsealed interface Node
sealed interface ParentNode : Node
sealed interface ChildNode : Node
sealed interface SourceNode : ParentNode
sealed interface OpNode : ParentNode, ChildNode
sealed interface SinkNode : ChildNode
Although maybe this has issues I havent thought of. Sadly seems like this is on the backburner - I'm not sure if without this or some other new language feature this type of idea may be impossible to express in kotlin?bbaldino
09/12/2019, 11:13 PMrook
09/13/2019, 4:08 PMsealed class
children, you also defined them as sealed class
. Which is a little strange unless you intend for them to also have their own internal classes.bbaldino
09/13/2019, 5:24 PMclass OpNode : Node(), ChildNode(), ParentNode()
)Emilio
09/17/2019, 6:26 PM