Skip to end of metadata
Go to start of metadata

Motivation

In Java, we are used to classes named *Utils: FileUtils, StringUtils an so on. The famous java.util.Collections belongs to the same breed. And the unpleasant part about these Utils-classes is that the code that uses them looks like this:

Those class names are always getting in the way. We can use static imports and get this:

This is a little better, but we have no or little help from the powerful code completion of the IDE. It would be so much better if we could say

But we don't want to implement all the possible methods inside the class List, right?

So, Kotlin (after C# and Gosu) introduces extension functions: a function declared outside the class List may be contributed to this type as an extension. This is denoted by prepending the receiver type (the one being extended) to the function name:

fun List<Int>.swap(x : Int, y : Int) { 
  val tmp = this[x] // 'this' corresponds to the list 
  this[x] = this[y] 
  this[y] = tmp 
}

The this keyword inside an extension function corresponds to the receiver object (the one that is passed before the dot). Now, we can call such a function on any List<Int>:

val l = list(1, 2, 3) 
l.swap(0, 2) // 'this' inside 'swap()' will hold the value of 'l'

Of course, this function makes sense for any List<T>, and we can make it generic:

fun <T> List<T>.swap(x : Int, y : Int) { 
  val tmp = this[x] // 'this' corresponds to the list 
  this[x] = this[y] 
  this[y] = tmp 
}

We declare the generic type parameter before the function name for it to be available in the receiver type expression. See Generic functions.

Extension functions are resolved statically

To avoid confusion, we would like to emphasize that extension functions are resolved statically, i.e. they are not virtual by receiver type. On the other hand they can be member functions on some class and thus can be virtual in that class hierarchy.

Similar features in other languages

AspectJ has inter-type declarations.

Groovy has metaclasses.

Scala makes heavy use of implicit conversions, i.e. wraps values into adapters at runtime.

C# and Gosu have extension functions implemented similarly to our approach.

What's next

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Jul 21, 2011

    Anonymous

    It is not clear how Extension Functions are registered. I assume you have to use import (as in Scala), but wiki page is not clear

    I hope it is not registered globally as in Groovy and other dynamic languages. 

    1. Jul 21, 2011

      You are right, one uses import

  2. Jul 21, 2011

    It's a shame you used a custom mechanism to define extension methods rather than just saying that if the first argument of the static method is the same type as the object, it can be treated as a extension method  or called classicly.

    This would mean that all those hundreds of thousands of static methods defined in Java would be usable as extension methods rather than requiring them to switch to using your language. This would mean that you example would actually work even if the 'swap' method was in a plain old Java library.

    1. Jul 21, 2011

      It would definitely be bad idea to treat any static method be an extension to the type of it's first parameter. Indeed having all those hundreds of thousands methods in completion list for String or Int would be disaster

      1. Jul 21, 2011

        Lol, well they would not automatically be there, you would have to explicitly import then just like you do with static methods.

        What about following C# extension methods, as at least you can call all those extension methods from other languages that don't support them (just treat them like static methods) or would the Kotlin compiler implicitly add a first argument to the method called 'this' anyway?

        1. Jul 21, 2011

          C# has explicit this on the argument so you cannot use arbitrary legacy static method as extension function either.

          1. Jul 21, 2011

            You miss understand, you can still call them from languages without extension method support, by providing the first argument explicitly. What would the signature of a Kotlin extension method look like from Java code?

            1. Jul 22, 2011

              You'll be able to call our extension functions from, say, Java. As you have said, they just have an extra parameter.

              1. Jul 22, 2011

                Is it possible to access private fields in extension method?

                Please ignore this question, just knew that there is no way to declare a field in Kotlin

                1. Jul 23, 2011

                  There's no way to access anything private in an extension function that is declared outside of the receiver class

                  1. Jul 31, 2011

                    Can we rephrase that as, an extension function cannot access private or protected elements of its receiver.

                    1. Aug 01, 2011

                      More accurately extension function has the same access level as if it received the receiver instance among other parameters explicitly.

                      1. Aug 02, 2011

                        Then, trying to conclude, why is the exotic syntax needed for the declaration of extention functions?

                        You surely tried to avoid introducing this extra syntax by trying to use "plain old static functions" as extension functions, but couldnt for some reason.

                        Yea I know, no static function in Kotlin but there is the equivalent and I am not sure how to call them.

                        "Class object functions"  I guess, but it sounds like a tautology.

                        1. Aug 03, 2011

                          Note that if you define

                          fun String.foo() { ... }

                          it's called on objects of class String, not on the class itself:

                          "abc".foo()

                          So your analogy to static functions and class object members seems to be irrelevant.

                          1. Aug 03, 2011

                            Yes but isnt it just an illusion.

                            foo is not truly a member of String and doesnt have any access to String private members.

                            foo is not more privileged than any function inside your favorite StringUtils.

                            This is what I understand.

                            1. Aug 03, 2011

                              That's right. It's only a syntactic difference

                              1. Sep 25, 2011

                                Anonymous

                                I agree the exotic syntax is unnecessary verbiage.

                                And it is a very narrow syntax, as does not aid extension where the function required its caller to supply a "view bound", i.e. page 483 of Programming in Scala. This can be accomplished in any language with an input parameter that is a function that inputs the type to be view bounded and returns the desired interface of the bound. The JIT can probably optimize away the runtime overhead.

                                If you are aiming for simplicity over Scala, then you don't want to add narrow duplicitous syntax. Aim for regularity and consistency instead. I would deprecate this while you still can.

                                -Shelby Moore III

                                1. Sep 25, 2011

                                  I don't see how absence of view bounds in Kotlin makes extension functions "unnecessary verbirage".

                                  To date, there are rather many use cases, both in Kotlin and C#, where extension functions work very well. For example, consider this section.

                                  1. Sep 25, 2011

                                    Anonymous

                                    I see how you use the feature for builders, but my point remains that I don't see why you need the special definition site syntax. Simply make all functions that input an object as the first parameter, callable as object.function(...) or function( object, ...). I don't see why you need to have another complex syntax to explain and users to memorize. The control over which functions are applied is done with import any way. If you need another vector of control, you could add an option on the import keyword, this would be more orthogonal because then any functions could be imported with either functionality.

                                    It is your language, I am just offering my feedback, given I am also designing a language that is trying to simplify Scala. Any way, I am designing an immutable language, so we are not competing, and I sharing with you some of my design principles. Apologies.

                                    I added a comment to the builder section. I will try not to bother you now. Good luck.

                                    -Shelby Moore III

                                    1. Sep 26, 2011

                                      Absolutely nothing to apologize for. We really appreciate your feedback and suggestions.

                                      Overall, I think, your point about the overly big difference in syntax is valid.

                                      A big problem with making any function callable in the "firstArgument.function(otherArguments)" form is that when you type in "foo." in an IDE, and press Ctrl+Space you don't really want all the functions that take the type of foo as the first argument in the completion proposal list, because only some of them are intended to be used this way.

                                      C# uses this as a prefix to the receiver parameter of an otherwise regularly defined function. We could simply say

                                      fun example(this : Foo, other : Bar) { 
                                        ... 
                                      }

                                      Instead of

                                      fun Foo.example(other : Bar) { 
                                      }

                                      And we are considering this as an option.

                                      1. Sep 27, 2011

                                        Anonymous

                                        What I suggested in the prior comment is to enable batch control over which functions are classified as eligible, by specifying it on import, i.e. import name[this] ... instead of import name..., or something like that.

                                        That way functions can be reused either way. I am thinking don't hardcode the option at the function site, but rather leave it optional at the import. Haven't thought about it too deeply though.

                                        1. Sep 27, 2011

                                          Well, what happens if you have a function in scope already (by direct definition or inheritance)? Can you call it this way, or do you need to import something you already see to do it?

                                          1. Sep 27, 2011

                                            Anonymous

                                            Hi, I am very glad I read this page, because it caused me to think deeply about extension. I think I now realize that we can't handle extension in this fashion. We need to handle it with the vtable and mixins, in order to be fully generalized and compositional. Which should also provide the explicit code completion intelligence control you desire as a side-benefit. I will email you now to the email address you have listed on your username, because I composed something (for my own language, and I think maybe it is applicable to Kotlin), but it is too long to post here, and which might require back-and-forth discussion that it might get unwieldy here. If there is any merit in my idea, perhaps we can report findings here after discussing it in email-- that is if you find my email interesting. I am not knowledgeable enough about vtables on JVM, so that is another reason I hesitated to post it here, until the idea has been vetted.

                                            Best,

                                            - Shelby Moore III

                                            1. Sep 27, 2011

                                              Thanks a lot for your effort. It makes sense to submit your suggestion as an issue to our tracker:

                                              http://youtrack.jetbrains.net/issues/KT

                                              Email is also fine, if you prefer it.

                                      2. Sep 27, 2011

                                        Anonymous

                                        Tangentially, the way I am handling this in my language, is through interfaces. Nothing is accessible, except via an interface. So this selection of which functions behave like methods is done through typing which is the most granular and I think perhaps the most "correct" from a type theory perspective.

                                        So if I want object with such methods, I input an interface with those methods, or I input a helper function which can convert one interface to another (i.e. a "view bound"). The caller is responsible to provide the conversion. This is the D principle in SOLID, a/k/a inversion-of-control or Hollywood principle. Gilad Bracha writes about this on his blog, "Constructors Are Considered Harmful". Meaning that we never want to hard-code implementation and limit the caller's compositionality. This was one of the main mistakes I saw in every language, is they allow class (and global functions, i.e. Scala's singleton object) to be a referencable type. And Scala conflated mixin implementation with interface in one trait.

                                        The downside of my design is that caller has to build an object at runtime of desired type, but I am thinking this can be optimized away by the Hotspot JVM. The upside is that inversion-of-control is explicit and granular.

                                        I realize your goals are somewhat different than mine, because I am aiming for a pure, immutable language (but not lazy a la Haskell). Whereas, you appear to be trying to provide an imperative improvement over Java, that is more straightforward than Scala.

                                        Perhaps we can collaborate in the future.  Email is shelby attr coolpage dotter com

                                        -Shelby Moore III

                                        1. Sep 28, 2011

                                          On the "JVM will optimize this": as the situation with java.util.Iterator shows, Hotspot really struggles with eliminating even really short-living objects from the heap. Maybe it will do a good job one day, but this day hasn't come yet.

                                  2. Sep 27, 2011

                                    Can we really do that same kind of markup builder using c# and its extension methods ?

                                    1. Sep 27, 2011

                                      The syntactic form Kotlin and Groovy offers will be problematic for C# due to lack of extension function literals.

                                      1. Sep 28, 2011

                                        Can a Kotlin class multiple-inherit from (classes|traits|mixins) sets of commonly used extension functions?

                                        1. Sep 28, 2011

                                          I'm not sure I understand what you mean. A big difference between classes/traits and extension functions is that class/trait members are dispatched dynamically, whereas extension functions are dispatched statically.

                                          Could you provide a use case you have in mind?

                                          1. Sep 29, 2011

                                            class StringExtensions { 
                                            fun String.before(s : String) { 
                                            StringUtils.substringBefore(this, s); 
                                            } 
                                            fun String.after(s : String) { 
                                            StringUtils.substringAfter(this, s); 
                                            } 
                                            } 
                                            class CollectionExtensions { 
                                            fun <T> Collection<T>.before(t : T) { 
                                                ... 
                                            } 
                                            fun <T> Collection<T>.after(t : T) { 
                                                        val index = this indexOf t; 
                                                        if (index == -1 || index == this.size() - 1) { 
                                                            return null; 
                                                        } else { 
                                                            return this.get(index + 1); 
                                                        } 
                                                    } 
                                            } 
                                            class Work1 extends StringExtensions, CollectionExtensions{ 
                                                fun work() { 
                                                    assert "aabbcc".after("bb") == "cc" 
                                                    assert [1,2,3].after(2) == 3 
                                                } 
                                            }
                                            1. Sep 29, 2011

                                              We do not encourage (mis)using inheritance for importing. The easy way to handle this case would be with imports:

                                              namespace stringExtensions { 
                                              fun String.before(s : String) { 
                                              StringUtils.substringBefore(this, s); 
                                              } 
                                              fun String.after(s : String) { 
                                              StringUtils.substringAfter(this, s); 
                                              } 
                                              } 
                                               
                                              } 
                                              namespace collectionExtensions { 
                                              fun <T> Collection<T>.before(t : T) { 
                                                  ... 
                                              } 
                                              fun <T> Collection<T>.after(t : T) { 
                                                          val index = this indexOf t; 
                                                          if (index == -1 || index == this.size() - 1) { 
                                                              return null; 
                                                          } else { 
                                                              return this.get(index + 1); 
                                                          } 
                                                      } 
                                              } 
                                               
                                              namespace foo { 
                                               
                                              import stringExtensions.* 
                                              import collectionExtensions.* 
                                               
                                              class Work1 { 
                                                  fun work() { 
                                                      assert "aabbcc".after("bb") == "cc" 
                                                      assert [1,2,3].after(2) == 3 
                                                  } 
                                              }
                                              1. Sep 29, 2011

                                                Ok nice I finally get it.
                                                This example would be nice at the top of this page.
                                                It would have avoided a couple of confusion in the comments of this wiki page.

                                                Plus a minimalist example for Extension function literals and then refer to markup builder for a real use case.
                                                These literals are new for almost everybody and they justify what I was calling the "exotic syntax"
                                                http://en.wikipedia.org/wiki/Extension_method does not even talk about these literals.

                                                A small example is worth a thousand words.

      2. Dec 03, 2011

        Agreed - though it would be nice to be able to explicitly import static Java methods as extension functions. (A bit like static imports in Java). There's a ton of really useful methods out there in various libraries; it'd be nice to be able to import them as extension methods without having to hand craft Kotlin delegation methods.

        So while I totally agree all static Java methods shouldn't be imported as extension functions by default; it would be good to be able to import them explicitly; maybe in a module definition or something? Or maybe just via the import statement?

          1. Dec 04, 2011

            Awesome thanks :) 

  3. Aug 05, 2011

    namespace NS1
    {
    fun Int.Method() = 10
    }
    namespace NS2
    {
    fun Int.Method() = 20
    }
    namespace NS3
    {
    import NS1; import NS2;
    fun Test() = 10.Method() // ????? NS1.Method or NS2.Method is called ???
    }
    In C# we can call extensioan methods as static method to solve this problem. And Kotlin??

    1. Aug 05, 2011

      In Kotlin we can rename on import.

  4. Aug 23, 2011

    Hi,

    what's about extension properties? for example,

      fun Collection.IsNotEmpty = ! this.IsEmpty

      fun Character.IsVowel = this.toLowerCase() in [ 'a', 'e', 'i', 'o', 'u', 'y' ]

    That looks nice, isn't it?

    Then, using

      if (mySet?.IsNotEmpty) doSomething(mySet)

    looks better than

      if (mySet?!IsEmpty())  doSomething(mySet)

    why not?

    1. Aug 23, 2011

      We support extension properties:

      val String.isEmpty : Boolean 
        get() = this.length() == 0
  5. Sep 01, 2011

    Maybe it's a typo in the example about generic swap function:

    And you mean:

    1. Sep 01, 2011

      Fixed. Thank you

      1. Oct 26, 2011

        Anonymous

        This is not a typo. vars x and y are indexes, not the data, so they should be Int

        1. Oct 26, 2011

          Oh, thanks a lot!

  6. Dec 02, 2011

    Okay this will be my last attempt to change your minds! Please have a look at Xtend's static extension methods they are doing exactly what I am talking about:

    import static extension java.util.Collections.*

    This is so much simpler, and I really do feel you are missing a trick not allowing standard Java methods to be treated as extension methods. It seems to me that your arguments are based on the performance of your IDE autocomplete / index size rather than the easy of use plus all of those Java 'extension' methods sitting there waiting for some one to use them.

    In fact if Kotlin did the same syntax, maybe one day Java might copy the syntax

    1. Dec 02, 2011

      I think we can support this for functions coming from Java. I filed an issue in our tracker: http://youtrack.jetbrains.net/issue/KT-732
      Thanks for the idea!

      For Kotlin functions, this is not that interesting, because a lot is driven by having a default receiver this inside extension functions, see Type-safe Groovy-style builders.

  7. Feb 17, 2012

    One of motivation to introduce extension methods to C# is LINQ. But we can not make analog of LINQ because there is not "expression trees" in kotlin. Do you plan to implement this feature?

    1. Feb 17, 2012

      Yes

  8. Jul 19, 2012

    There is an important difference between class methods and extension methods regarding inheritance. Maybe you can illustrate is with simple example:

    open class Parent { 
      open     fun virtualCall() = println("virtual call parent") 
    } 
    class Child : Parent() { 
      override fun virtualCall() = println("virtual call child") 
    } 
     
    fun Parent.extensionCall() = println("static call parent") 
    fun Child .extensionCall() = println("static call child") 
     
    fun main(args : Array<String>) { 
      val p  : Parent = Parent() 
     
      val c1 : Parent = Child() 
      val c2 : Child  = Child() 
     
      p.virtualCall()    // -> parent 
      c1.virtualCall()   // -> child  - overridden virtual call 
      c2.virtualCall()   // -> child 
     
      p.extensionCall()  // -> parent 
      c1.extensionCall() // -> parent !!! due to variable definition as Parent 
      c2.extensionCall() // -> child 
    }

    This might be quite unexpected.

    1. Jul 19, 2012

      Thanks for the suggestion. BTW, it's the same as overloading.

  9. Jul 19, 2012

    I tried to make another example:

    class Test { 
      fun foo() = println("virtual call foo") 
      fun baz() = println("virtual call baz") 
    } 
     
    fun Test.foo() = println("static call foo") // will never be called 
     
    fun main(args : Array<String>) { 
      val t = Test() 
      t.foo() // -> virtual 
     
      fun Test.baz() = println("extension call baz") 
      t.baz() // -> extension! the function is defined within the method 
    }

    So, it looks like there is no way to call the static function foo() - it tries to override virtual function with exactly the same signature, but virtual calls have priority. In my opinion, defining such extension function should lead to a compiler error (with the hint text that such functions can be defined within another function).

    I mean, for normal methods we require "override" annotation in such cases.

    Also, I could not find resolution rules in the documentation - apparently I learned the trick of re-defining existing functions (within the method) from one of your presentations, not from the wiki.

    So, my suggestion would be:

    // ... 
    fun Test.foo() = println("static call foo") // compiler error 
    override fun Test.foo() = println("static call foo") // if function can be somehow imported and used, then OK. Otherwise - also error 
     
    fun main(args : Array<String>) { 
      val t = Test() 
      t.foo() // -> virtual 
     
      override fun Test.baz() = println("extension call baz")  // I explicitly say that I want to override virtual function with the static call 
      t.baz() // -> extension! the function overrides the normal method 
    }
    1. Jul 19, 2012

      We will add a compiler message (error or warning) when an extension can't be called.

      I think, your "override" proposal is too dangerous.

      Thanks

  10. Aug 31, 2012

    Hi Andrey, Im trying kotlin for the first time, but I can't get your swap() extension example to work from inside my java classes.

    Do I need to add something to the calling java class?

    1. Aug 31, 2012

      If you show me the code, I'll try to help you

  11. Aug 31, 2012

    This is for the kotlin code, I just pasted your code

    ------------------------------------------

    ---------------------------------------------------

    The java code that produces a compiler error, for swap() not being recognized

    ---------------------------------------------

    1. Aug 31, 2012

      We can't alter the Java programming language and teach it to understand extension functions.
      You can call your swap() as a static method, though: