Hello, I am (attempting) to write a library that supports both mutable and immutable representations of genetic data. Obviously, the mutable representation of the data should adhere to the same interface as the immutable representation because it can perform all the same functionality as the immutable representation. This is where I start to run into some trouble.
The data is represented in a tree structure. Any node that has children is an “Ancestor” while nodes that carry genetic information are called a “Feature.” A node that is an ancestor but not a feature is a “Genome,” which represents the root of the entire tree.
Here is a reduced version of the code to show subtyping relationships.
public sealed interface Ancestor : Iterable<Feature>
public sealed interface MutableAncestor : Ancestor, Iterable<MutableFeature>
public sealed interface Feature
public sealed interface MutableFeature : Feature
My assumption was that since the iterator only ever produces and never consumes the type specified, that this type of override would be legal. However, the compiler produce the following error “Type parameter T of iterable has inconsistent values: Feature, MutableFeature.” It is not clear to me why this arrangement would cause an issue. I want to ensure that the client can get access to a node as a MutableAncestor and concisely iterate over its descendents without having to cast each one of them to a MutableFeature.
Is there a good workaround to accomplish what I want to accomplish?