Lets talk about extensions in new way


#1

I very like Swift extensions. My propose is to have smth similar. Use case:
When I need to somehow separate private functions from interface implemented methods in Repository or Service, its kind a mess.

Ex:

interface SomeInterface {

    fun productList(): List<Product>
}

class BuissnesLogicClass(val service: Service): SomeInterface {

     override fun productList() {
       // 1. It would be nice to acces checkSmth(here)
    }

}

// Swift like exension.
private extension BuissnesLogicClass {

     fun checkSmth(): Bool {
        //  to make this check I need service,
       //  there is no way to access in current extensions implementations
    } 
}

#2

Can’t you use extension functions?


#3

I can, but I have no access to injected services for exemple.


#4

should service be private?
because this function:

private fun BusinessLogicClass.checkSmth() = service.check()

just works

Having said that, I like the idea of grouping the exension-functions as I said before.
In that way, you don’t need to repeat the receiver for every extension-function.


#5

If a class is going to call an extension function defined for it, I think it should not be an extension function. Make it a member function instead, because it seems to me that the extension function is core functionality that the class needs to fulfill its responsibility.

Extension functions are meant to be used to extend third-party classes that you cannot modify yourself.


#6

ok, thx


#7

For this example it may be true, but actually there are many cases where you want shared functionality that has some state. You can achieve this with an interface, but that has to be inherited publicly:

interface InterfaceExtension {
    val data:Data
    
    class Data(var d: Int = 0) // some data

    fun doSomething() { println(data.d); data.d++ }
}

class A private constructor: InterfaceExtension {
  override val data= Data()
}

Using this pattern I can get a limited form of multiple inheritance. What it doesn’t allow me is to keep this as implementation detail. I don’t want InterfaceExtension to be in the signature (nor should val data:Data be public). I do want the elegant syntax that the interface gives me without having to declare forwarding functions (not needing to invoke them as data.doSomething().

A more important benefit for an extension is that it allows for the extension functions to be very easily be used in the public interface of the class without the implementation extension being public.


#8

I think you are starting off this discussion wrong. Most languages call the idea you want as a “mixin”, “trait”, or “typeclass”. I will give you that swift calls them extensions. I would love this in Kotlin. There is a library to do typeclasses at runtime called Arrow. I know they want to be able to add compile time verification, but I don’t know where that is at. There is also a giant Kotlin discussion about this.