Note that my question is not platform specific so that's why I don't add the [kotlin] tag (the code is in Kotlin). If there is a Kotlin-specific answer I'd like to hear about it though
I am working on a simple component (GUI) library and I have the following interfaces:
interface Component : Drawable, Positionable, Identifiable {
fun getComponentStyles() : ComponentStyles
fun setComponentStyles(componentStyles: ComponentStyles)
}
interface Container : Component {
fun addComponent(component: Component)
}
Internally I have some base classes which implement the common functionality (DefaultComponent
, and DefaultContainer
). My problem is that I have some methods which I would not like to expose to the external world like:
fun fetchComponentByPosition(position: Position): Optional<out Component>
I can use DefaultComponent
internally but the problem is that the user is able to call addComponent
which will add a Component
to a Container
and obviously a Component
is not a DefaultComponent
. I can make an other interface
which is implemented by DefaultComponent
but it won't solve the problem which is invariance here.
Currently I have Builder
s for all Components
and all Component
implementations use DefaultComponent
as a base class so I can cast Component
to DefaultComponent
salfey but this is a hack at best.
So my question is this: how can I hide the internal API when I have to use invariant interfaces (by invariant I mean that I both return and accept classes with a specific interface
and I can't downcast them safely).?
internal
interface for your internal methods?DefaultComponent
cast succeed) while at the same time disavowing its existence, unless the cast occurs inside your library within a suitable scope. You have to find something that can be declared with aninternal
scope, which is why I was suggesting that you use an abstract class.