Might be nice to declare extension methods without repeating the type

Was looking at some extension methods and properties I had declared and saw something like this:

fun SomeReallyLongTypeName.method1() { ... }
fun SomeReallyLongTypeName.method2() { ... }
val SomeReallyLongTypeName.property1: SomeType get() = // ...
val SomeReallyLongTypeName.property2: SomeType get() = // ...

And was thinking about the way Dart declares extension methods (https://dart.dev/guides/language/extension-methods) and in Dart extensions are always declared in an extension block. So in Dart that would be:

extension MyExtension on SomeReallyLongTypeName {
    method1() { ... }
    method2() { ... }
    SomeType get property1 = // ...
    SomeType get property2 = // ...
}

which is easier to read with less boilerplate.

Would be nice if Kotlin had a similar capability to declare a block of extensions and not have to repeat the type name over and over.

7 Likes

This would be extra helpful if kotlin decides to accept the mutliple recievers KEEP.

2 Likes

What about using typealias to make the name shorter?

Yes using a type alias can make the name shorter, but still doesn’t address the root issue. For one thing you then have the cognitive load of having to know what type the alias is referring to. If you have a lot of extensions then that alias my be hundreds of lines away. It would be more convenient and easier to read if you could declare extensions as a block

To be honest the argument that the type alias might be hundreds of lines away is also an argument against this way of declaring extensions. After all the same could be said for the top of the extension block so that would be equally far away.

Anyways, I feel like this would be most feature would be most useful for a large number of extension functions/properties that can be written as 1 liners, maybe 2-3 lines. I could see this being useful for wrapper libraries around native or java libs. Once functions get larger however I don’t think that this would make much of a difference and might be even a disadvantage.

But that argument could also be made about the non-extension methods declared inside the class. The top of the class could be hundreds of lines away yet we don’t have a problem in that case because we are talking about a nested context which (not sure best how to describe it) is less cognitive load. After all they could have done it like C++ where the class name has to be a prefix on every class method, but I think we would agree the ability to just nest them is easier to read.

I am not suggesting that it be required to declare them in a block, but if it were possible it could improve readability. Any feature can also be abused to decrease readability.

1 Like

I use Swift often and I want this feature in Kotlin too.

In Swift it is simple:

extension String  {
    func method1() { self is String }
    func method2() { ... }
    var property: Int {  }
}

or a more complex one:

extension Array where Element == String //or Element: Protocol
 {
func getAll() { ... }
}

so I would suggest:

extension String  {
    fun method1() { this is String }
    fun method2() { ... }
    var property: Int get() = 42
}
1 Like

In Dart there is an optional name for the extension block which is used for importing the extensions so you can import all the extensions with one import.

Based on my limited experience so far, I’m not sure how prevalent this use case is, let alone whether the prevalence/usefulness of a new feature balances out the increase in language complexity (if you have ever looked through a modern C# book, you may understand what I mean).

Anyway, at the moment I myself am not convinced that the benefits of brevity outweigh the benefits of readability and simplicity (though I guess that is ultimately for the Kotlin team to decide).

I am wondering though what the least ‘exotic’/‘surprising’ or most natural way to achieve this goal would be? ‘extension’, at the very least, does not seem a current keyword in Kotlin.

perhaps

with (String) {
fun f1() = …
}

may be better… but if anyone has some more/better ideas about natural/easy to read/remember syntax, that may help to get this feature in.

1 Like

It doesn’t seem like a big deal, IMHO.

1 Like

Is it a huge deal? No. But would be a nice reduction in boilerplate in some cases where you have multiple extensions on type with a long name.

As suggested, this issue was addressed by type alias.

The extension interfaces are a huge deal and shortening the name of the receiver seems irrelevant in its scope. The idea of extension interface is to be able to declare an interface (not implementation) and be able to declare types as ones having some kind of extension interface implemented on them. It is more or less the idea of KEEP-87. It requires significant design efforts.

The other possibility, as @Wasabi375 mentioned is already available. You can declare an interface or an object with member extensions and apply this object with with method. There is also a section in the KEEP-176 discussion about providing class-level receivers. It would allow avoiding those long names inside the extension class. Of course in order to do it properly, one needs full multi-receiver mechanics. In my opinion, this way is much more flexible.

1 Like