Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

If you got time, play around with extensions with multiple receivers, you can do pretty neat stuff with them.

See my comment here: https://news.ycombinator.com/item?id=14365317



What's the advantage of extension functions compared to plain functions?

  fun String.shout() = this + "!!!"

  fun shout(s: String) = s + "!!!"
Looks pretty much the same to me. Extension functions use static dispatch so what's the point of using member syntax?

Also, extension functions can be overwritten by a member function with the same signature. That seems quite fragile to me considering the class and the extension function very likely have different authors.

That said, I don't know Kotlin very well. So perhaps you can set me straigt on any misconceptions I may have.


Besides what Larrikin said, discoverability. Discoverability is the killer feature of languages designed for IDE support that you just won't understand if you haven't seen it. It's a big reason of why Kotlin beats Scala in practice, IMO (1).

I code Elixir a lot these days and spend a lot of time looking at hexdocs.pm and occasional library source code. With Kotlin or C#, this is seldomly necessary, because the IDE's autocomplete tells you everything you can do with this object. It doesn't guess, it knows. If it's in the list, you can do it, if it's not, you can't.

Now, if I have a string object called "str", and I write "str.", I want to see a list of everything I can do with it. But a MyStringUtils.shout() is never in that list, because it does not come after the dot.

With extension functions, this becomes possible with userland extensions to existing classes and interfaces. All you need is a single import on top, and good IDEs (eg. visual studio) can also auto-import that one if you use a function from it once.

(1) Last I tried, Scala was too slow to compile to provide 100% perfect autocomplete within a few milliseconds. IntelliJ did some Python-esque guesswork to mitigate that, but that effectively reduces the feature to "save me some keystrokes", i.e. not very useful. Maybe this has been fixed since.


I used extensions with multiple receivers for adding context inside data-structures.

Example: I have a layout-algorithm for a grid that takes sections:

    interface Section {
        val title: String
        fun something()
    }
Then I have the grid-algorithm. Inside I store expanded/collapsed state for each section. When I use a member-extension with both receivers I can write that pretty conveniently:

    class GridLayout(sections: List<Section>) {

        /* the state */
        val expandedSections = mutableSetOf<Section>()

        /* the extensions I need in this context */
        val Section.isExpanded get() = this@Section in expandedSections
  
        fun Section.expand() = expandedSections += this@Section

        
        fun compute() {
            ...
            if (!section1.isExpanded) {
                section2.expand()
            }
            ...
        }

    }


This looks neither clear nor convenient to me.


I use extension functions on classes I don't own to add functionality I think the class should have had or would be extremely useful for my project if a certain type of class had the functionality. Your example would require a static utility class in Java or an object in Kotlin to use every where, the extension functions can just be inside of a kotlin file.

So the difference would be in Kotlin

  object StringUtilClass() {
    fun shout(s: String) = s + "!!!""
  }

  import StringUtilClass.*
  StringUtilClass.shout("I'm mad")
vs

  fun String.shout() = this + "!!!"

  import StringExtensions.*
  "I'm mad".shout()
Kotlin doesn't always add brand new functionality, it also strives to make it faster to read and write code.


That surprises me. I would have thought that you could do this in Kotlin just as you can in Java with static import:

  import StringUtilClass.*
  shout("I'm mad")


Personally I find that less clear where shout is coming from and how to use it. It would also make autocomplete less useful as mentioned


Members can be chained, which improves readability a lot.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: