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

  • 1
    Can you declare a separate internal interface for your internal methods? – Robert Harvey Aug 24 '17 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. – Robert Harvey Aug 24 '17 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. – Robert Harvey Aug 24 '17 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. – Robert Harvey Aug 24 '17 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 '17 at 20:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.