1

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 Builders 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).?

20
  • 1
    Can you declare a separate internal interface for your internal methods? Aug 24, 2017 at 15:01
  • 1
    I think your best bet would be to deal with a class API internally, not an interface API. This would give you a bit more flexibility with respect to visibility. You don't seem to need the capabilities that internal interfaces would provide; you would only need them if you intend to swap implementations, or have an especially complex inheritance tree. Aug 24, 2017 at 16:29
  • 1
    I am trying to say that I don't understand why you're not just calling the methods on the internal classes directly, instead of going through a semi-private interface. Aug 24, 2017 at 18:50
  • 1
    Then I'm afraid your stuck. You can't declare that something publicly exists (which is what you need to make the 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 an internal scope, which is why I was suggesting that you use an abstract class. Aug 24, 2017 at 19:18
  • 1
    Robert hits the nail on its head with the internal visibility-modifier for C#. I don't think you can do what you're asking in Kotlin: discuss.kotlinlang.org/t/…
    – Jan Sommer
    Aug 24, 2017 at 20:16

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.