The documentation for Kotlin is now located on the new site. This page is kept for historical reasons

Skip to end of metadata
Go to start of metadata

The documentation for Kotlin is now located on the new site. This page is kept for historical reasons

Kotlin allows us to provide implementations for a predefined set of operators on our types. These operators have fixed symbolic representation (like '+' or '*') and fixed precedence. To implement an operator, one provides a member function or an extension function with a fixed name, for the corresponding type, i.e. left-hand side type for binary operations and argument type for unary ones.


Here we describe the conventions that regulate operator overloading for different operators.

Unary operations


Translated to







This table says that when the compiler processes, for example, an expression +a, it performs the following steps:

  1. Determines the type of a, let it be T.
  2. Looks up a function plus() with no parameters for the receiver T, i.e. a member function or an extension function.
  3. If the function is absent or ambiguous, it is a compilation error.
  4. If the function is present and its return type is R, the expression +a has type R.

Note that these operations, as well as all the others, are optimized for Basic types and do not introduce overhead of function calls for them.


Translated to


a.inc() + see below


a.dec() + see below

These operations are supposed to change their receiver and (optionally) return a value.

inc()/dec() shouldn't mutate the receiver object


By "changing the receiver" we mean the receiver-variable, not the receiver object.

The compiler performs the following steps for resolution of an operator in the postfix form, e.g. a++:

  1. Determines the type of a, let it be T.
  2. Looks up a function inc() with no parameters, applicable to the receiver of type T.
  3. If the function returns a type R, then it must be a subtype of T.

The effect of computing the expression is:

  1. Store the initial value of a to a temporary storage a0,
  2. Assign the result of a.inc() to a,
  3. Return a0 as a result of the expression.

For a-- the steps are completely analogous.

For the prefix forms ++a and --a resolution works the same way, and the effect is:

  1. Assign the result of a.inc() to a,
  2. Return the new value of a as a result of the expression.
Binary operations


Translated to

a + b


a - b


a * b


a / b


a % b




For the operations in this table, the compiler just resolves the expression in the Translated to column.


Translated to

a in b


a !in b


For in and !in the procedure is the same, but the order of arguments is reversed.


Translated to



a[i, j]

a.get(i, j)

a[i_1, ..., i_n]

a.get(i_1, ..., i_n)

a[i] = b

a.set(i, b)

a[i, j] = b

a.set(i, j, b)

a[i_1, ..., i_n] = b

a.set(i_1, ..., i_n, b)

Square brackets are translated to calls to get and set with appropriate numbers of arguments.


Translated to



a(i, j)

a.invoke(i, j)

a(i_1, ..., i_n)

a.invoke(i_1, ..., i_n)

Parentheses are translated to calls to invoke with appropriate number of arguments.


Translated to

a += b


a -= b


a *= b


a /= b


a %= b


For the assignment operations, e.g. a += b, the compiler performs the following steps:

  1. If the function from the right column is available
    1. If the corresponding binary function (i.e. plus() for plusAssign()) is available too, report error (ambiguity).
    2. Make sure its return type is Unit, and report an error otherwise.
    3. Generate code for a.plusAssign(b)
  2. Otherwise, try to generate code for a = a + b (this includes a type check: the type of a + b must be a subtype of a).

Note: assignments are NOT expressions in Kotlin.


Translated to

a == b

a?.equals(b) ?: b.identityEquals(null)

a != b

!(a?.equals(b) ?: b.identityEquals(null))

Note: identityEquals checks if two references point to the same object.

The == operation is special in two ways:

  1. It is translated to a complex expression that screens for null's, and null == null is true.
  2. It looks up a function with a specific signature, not just a specific name. The function must be declared as
    Or an extension function with the same parameter list and return type.


Translated to

a > b

a.compareTo(b) > 0

a < b

a.compareTo(b) < 0

a >= b

a.compareTo(b) >= 0

a <= b

a.compareTo(b) <= 0

All comparisons are translated into calls to compareTo, that is required to return Int.

Infix calls for named functions

One can simulate custom infix operations by using infix function calls.

What's next

  • No labels


  1. Anonymous

    It would be nice if I could declare equals() as strongly typed for my class - i.e. "equals(other: MyClass): Boolean" rather than "equals(other: Any?): Boolean" - and let the implementation == insert type and null checks as needed.

    1. There're two problems:
      1) It's Java-incompatible
      2) What if you have a dozen functions like equals(A), equals(B), ... defined for your type? What should the compiler do: call each of them? One of them? In what order?

      1. Anonymous

        Well, you solve that problem somehow when rewriting "a+b" as "a.plus(b)", so I'd assume the same to be true for "==" / "equals" - overload resolution failure? But I guess "==" is special in that, in your type system, it can be applied to any type at all.

        Then, perhaps, provide some syntactic sugar that would let write the body of "equals" with no need for extra checks (so as to adhere to DRY), but expand it to "equals(Any?)" in compiled version? This could be made even shorter then, since the compiler can infer the type of argument (as same class) and type of result (as Boolean); for example.:

        (though then the obvious question is, "why can't I write fun+() etc?")

        Either way, I think that defining equality should be no more verbose than defining any other binary operator. If I don't need any type/null checks to implement "a+b", I shouldn't need any for "a==b", either.

        1. You'll have your custom compiler extension generate equals for you. Like this:

           fun equals(other : X) = this.foo == other.foo

          And it creates a proper equals for you... expand is just an annotation here.

          1. Anonymous

            Cool, but can we have it in the stock library? It just seems such a common thing that repeating it over and over again for every project makes little sense - it would be .NET's Enumerable.Zip all over again :)

      2. Strongly typed equals looks nice. In order to provide compatibility with java,
        the compiler can generate a wrapper that accepts object, checks the class
        and calls the strongly typed equals.

        In case of several equals with different types of the argument - what they are for? may be to restrict them?

        1. See above about the "expand" annotation

    2. I've also recognized the problematic. I also develop as strongly typed as possible. But it's important to implement the comparison logic in the method

      fun equals(other : Any?) : Boolean

      ... so that derived classes only have to override one method.

      A good solution would be, if the compiler would show a warning (or denies the compilation), if one compares incompatible types.

      val a1 : Apple = pickAnApple() 
      val a2 : Apple = pickAnApple() 
      val del : Apple = GoldenDelicious() 
      val rus1 : Apple = Russet() 
      val rus2 : Apple = Russet() 
      val p : Pear = AnyPear() 
      val x1 = a1 
       p // Makes no sense. The compiler should show a warning. 
      val x2 = a1 == a2 // OK 
      val x3 = a1 == del // OK 
      val x4 = del 
       rus1 // Makes no sense. The compiler should show a warning. 
      val x5 = rus1 == rus2 // OK

      Very important is, that an explicit comparison with NULL will allways do a reference comparison and not call the equals-method.

      val y1 = a == b // --> a?.equals(b) ?: a.identityEquals(b) 
      val y2 = a == null // --> a.identityEquals(null) 
      val y3 = a != null // --> !a.identityEquals(null)
  2. Anonymous

    I personally like operator overloading since it is a very convenient feature. But a problem I often see with other languages is, that operator overloading can be abused. I think the language should restrict in this area and force the programmer to write semantically correct operators.

    A prominent example of this is in my opinion the plus-operator (+), which is a numeric operator. Hower, in almost all languages the +-operator is used for string concatenation. In my opinion, this is semantically incorrect since you do concatenate two strings and not (mathematically) add them together.

    I think Digital Mars with their programming language D is doing a good job in this regard as they don't just use the +-operator out of habit. Instead they defined an additional ~-operator for this purpose (SQL standard, not Microsoft SQL, also uses something different for concatenation):

    I don't know how Kotlin handles string concatenation, because I haven't found any examples (or did miss them). But I think this is something that you might want to consider.

    Another Idea from me was to limit the operator overloading to classes which implement a specific interface, e.g. NumericOperations (+ - * / %), BinaryOperations (& | ^ << >>) , ConcatenateOperations (~) and so forth.

    Something like:

    Well, that are my Ideas. I don't know how realizable they are as they aren't 100% thought-out. I also don't have much knowledge in the field of creating compilers and languages. However, it might be a good topic for discussion and perhaps even make Kotlin a better language. If not, I just wasted my time writing this text :-)

    1. You shouldn't consider your time wasted, that's for sure!
      It's rather hard to ensure overloaded operators are used for math and satisfy Field axioms, you know. Also, people are quite used to concatenate string with plus sign and one needs to argue with something more than purity reasons to change this.
      I personally like idea of ~ for concatenation BTW

      1. Anonymous

        I'd make an argument against "+" for a more practical reason: As an arithmetic operator, its precedence is too low. Also, it's very commonly used in non-string-concatenation contexts as well. So that leads, in Java, to potential bugs like this:

        int i=10;

        int bar();

        String s = "foo" + i*2+1 + "bar";

        The author presumably meant this to be parsed as:

        String s = "foo" + (i*2+1) + "bar";

        with the value "foo21bar", but it actually gets parsed as:

        String s = (("foo" + i*2)1)"bar";

        with the value "foo201bar".

        I've actually seen bugs like this happen in Java code.

        If a binary operator with lower precedence than "+" was used for string concatenation, the problem would have been avoided.

        I know that some languages use "&" for string concatenation instead of "+"...

        1. You will not be able to add an integer to a string in Kotlin anyway. You can only concatenate strings or add numerics with it. Your sample will be written as follows:

          1. Anonymous

            In that case, why do you need a string concatenation operator at all? Shouldn't the user just do this?

            val s1 = "foo"

            val s2 = "bar"

            val s3 = "$

            Unknown macro: {foo}


            Unknown macro: {bar}


            1. Anonymous

              Oops. Wiki screwed up my formatting. That should have been:

              val s1 = "foo"

              val s2 = "bar"

              val s3 = "${foo}${bar}"

              1. You're quite right. It's just a matter of taste anyway, not the error prone construct java's string concatenation with whatever used to be

  3. Anonymous

    How is associativity handled? If I write

    class Vector(...) { fun times(s: Double){...}}

    then v*s is straightforward v.times(s) but what about s*v?

    Or is that handled w/ extension methods?

    fun Int.times(v: Vector) = v.times(this)

    1. You can do an extension method. Otherwise it does not work.

  4. Anonymous

    Why did you decide to do plus and plusassign as member functions?

    And not as in .Net as static functions?

    Are there any (dis)advantages with either way to implement?

    Just curous

    1. It is basically the same thing with help of Extension functions

  5. Anonymous

    This is a lot of method names to remember to not use for other purposes. A lot of them are common names, too.

    It would be nice if an annotation or some kind of restricted method name namespace was required for operator overloading so that people wouldn't end up using one of these names by mistake. For instance, having all of the names preceded by an underscore or other special character, or using names like "opPlus", "opMinus", etc. which users would be unlikely to use (or want to use) for other purposes.

    1. Anonymous

      Python has the same problem (remembering the names of underlying operator functions)

      Personally, I would prefer a straight syntactic definition along the lines of C++ or C# (ie. public operator+(...))

      Whether it gets compiled down to a method named "plus" or "opPlus" or something that cannot be named in Java (eg. "<plus>") is another matter.
      (nameable would be good if you wan't to call from Java-side, un-nameable is good if you wish to avoid name-conflicts)

  6. Anonymous

    I think that "==" and "!=" as well all comparison operators should be implemented by different methods.

    It will dramatically simplify various DSL implementations. By the way Groovy is going to do in in it's 2.0 upcoming


    1. Anonymous

      Indeed, there are not too many symbols available for DSL:s here.  Maybe add a few unused ones, like ~, or iconographic combinations like arrow ->  (the range operator already looks like it will be very useful).

      I can see why the semantics of the comparison operators would be fixed though, it allows refactorings like !(a < b)  to  a >= b  to be done automatically, as well as manually without having to look into the implementation of the objects operated on.

      1. I am not sure if it is a good idea to have things with "no fixed semantics whatsoever". I understand the concern, but I thin in the current version we will refrain from adding these. Will see what demand there actually is.

  7. Anonymous

    Hello. Great you decided to include operator overloading in Kotlin.

    What do you think about the idea of making an explicit annotation for compiler?


    Without this annotation compiler would not compile implicit calls to the method and possibly warn programmer about using this name.

    Thinking anout the pros and cons of this idea, I decided it just would be much more clearer and easier to understand for new users of the language. Though it may be excessive.

    Just an idea I decided to share.

    1. This would require some magic to make Java classes work as we like. E.g., for Java's List to have proper element access with square brackets.

  8. there is some missunderstandig caused by .inc() description.

    fun main(args : Array<String>) {
      var x : I = I();
      var y : Int = 0;
      for (i in 1..10) {
        println("$x ${x++} $x $y ${y++} $y")
    class I {
      var i = 0;
         get() = $i;
         set(v) = $i = v;
      fun inc() : I {
        return this;
      fun toString() : String {
        return i.toString();

    0 1 1 0 0 1
    1 2 2 1 1 2
    2 3 3 2 2 3
    3 4 4 3 3 4
    4 5 5 4 4 5
    5 6 6 5 5 6
    6 7 7 6 6 7
    7 8 8 7 7 8
    8 9 9 8 8 9
    9 10 10 9 9 10
    that means that y++ behaves like ++y.
    it might be some mistake, but can't get where it is.

    1. fun main(args : Array<String>) { 
          var x : I = I(); 
          var y : Int = 0; 
         for (i in 1..10) { 
             println("$x ${x++} $x $y ${y++} $y") 
      class I(val i : Int = 0) { 
          fun inc() : I { 
              return I(i + 1); 
          fun toString() : String { 
              return i.toString() 

      This code yield the following result:

      0 0 1 0 0 1
      1 1 2 1 1 2
      2 2 3 2 2 3
      3 3 4 3 3 4
      4 4 5 4 4 5
      5 5 6 5 5 6
      6 6 7 6 6 7
      7 7 8 7 7 8
      8 8 9 8 8 9
      9 9 10 9 9 10

      Problem is that generated code saves the reference to x not the value, so when you call toString() in your example the value has already changed.

      If inc() returns another instance of I then x++ and ++x semantics work as expected.

    2. We should update the documentation to make it clear that inc() is not supposed to mutate the object it is called on.

      1. while writing that i knew what i was doing.

        That is not about documentation, this is about behavior.

        when i write x++ inside expression i mean that first i want expression to be counted, and then increment logic to run. ++x respectively first run increment logic and then count the expression.

        i do not want to make another instance of my object running unary operation at all. Here is the problem caused by new instance: 

        fun main(args : Array<String>) {
          var c1 = Counter(0);
          var c2 = Counter(0);
          println("${c1.value} ${c1.stateAffected}");
          println("${c2.value} ${c2.stateAffected}");
        fun affectCounter(c : Counter) {
        class Counter(initialValue : Int) {
          var value = initialValue
          get() = $value;
          var stateAffected = false;
          get() = $stateAffected;
          fun inc() : Counter {
            return Counter(value+1);
          fun affect() {
            stateAffected = true;
        1. As far as I can see, the behavior you are requesting is "copy the object behind the scenes". The platform we are working on does not allow us to do this... Any suggestions?

          1. that is the real challenge, actually. My first idea was to move increment itself next to expression. But there are two problems. First problem is that what if user decide to use increment like this: f(x+,x+) . That is absolutely crazy code, but this situation cant be solved while playing with tree (this function should work with non-incremented and incremented x same time). the second idea was to create a fork proxy object that will represent x's state before increment, but this way is even more difficult.

            Finally, i think that increment for an object is the real problem. Because. Ok. I see and i do not mutate an object, but return a new instance. But what if x.inc() just delegates increment-like functionality of x.y property, but mutates y. So i need to clone y too, but it is implemented by another guy, so i can't affect it.

            Оf course, i can always clone an object automatically, but i will have to clone it's members to, so i have a real chance to pull a hudge tail of dozens of objects. So copy is not an option to.

            Also i am sure, that if i will dig deeper tp .plus(x) function, i will find lots of troubles to, for example it is surely easy to brake transitive relation so that will lead to problems and fancy bugs.

            1. Yes. And it is not really specific to Kotlin: Java has the same problem, the only difference is syntax: in Kotlin you can say a + b, in Java it would be a.plus(b), but all the problems remain.

  9. and another problem

    fun main(args : Array<String>) {
      var c = C(1);
      var l = Looker(c);
      println("${l.c} ${c}");
    class Looker(c : C) {
      var c = c;
      get() = $c;
    class C(i : Int = 0) {
      var i = i;
      fun inc() : C = C(i+1);
      fun toString() = i.toString();

    shows, that .inc() is dangerously unsafe. If i use it somewhere, i need to keep in mind that everything pointing to this object will become invalid.

  10. For Collection.add operation can I use myList[] = "a" ?  

    Thank you, really loving this language - Matt  

    1. We do not allow this. I think

      Is good enough, isn't it?

      1. I do like infix operators.  The difference I see is precedence of equals is lowest.  

        Also "[]" is a Collection operator (get/set) and instead of misusing "+=" for adding items.

        1. The "[] =" notation looks too cryptic to me

          1. a[1];   // get

            a[1] = "value1"; // set

            a[] = "value2"; // append

            is very clear to me (this syntax is also used by PHP).

          2. matrix[i][]; //return row

            matrix[][i]; //returns column

  11. Why assignments are not expressions?

    So I need to write:

    Instead of simple:

    Is it only because named arguments?

    1. This should not be hand-coded every time you need to read from a stream.
      There must be a dedicated library routine for this, something like

      inputStream.readBuffered(buffer) { bytesRead -> 
        to?.write(buffer, 0, bytesRead) 
      1. Yeah, nice variant, thank you :)
        Still not accustomed to use function literals so actively

  12. One thought that might be interesting, although I immediately admit it might seriously degrade readability, is an implicit cast operator.

    So for instance a method like:

    would make casting from MyObject to String possible so we could write:

    Now with extension methods we could do some really interesting things like:

    But again, this might negatively affect readability.

    1. One huge problem with this is that you can not have several methods that differ only in their reTurn types

      1. That could be overcome by translating the methods:



        cast() : Date

        cast_java_util_Date() : Date

        In a way is just like translating from a + sign to a plus function or those new componentn convention functions.

        But I admit this doesn't make Kotlin necessarily easier to use or understand (let alone to implement).

        1. This is a common misconception: methods return types (e.g. Map<String, List<Foo>>), not classes, and types can not be identified by qualified names.

          1. True, hadn't thought of that.
            Don't do the above (wink)

  13. Apparently, function called 'invoke' can be used just like 'get', but with round brackets instead of square brackets. Please add it to the documentation here.

    fun main(args : Array<String>) { 
      val t = Test() 
      println("t(1) = ${ t(1) }") // prints t(1) = 2 
    class Test() { 
      fun invoke(v:Int) = v + 1 
    1. Done, thanks for the report

  14. Operator overloading + Extentsion functions = Magic:

    fun Unit.not() { 
        println("Fun. Unit. Not!"); 
    !println("We've got a message from outer space:")

    More fun:

    fun Unit.rangeTo(same: Unit) {} 

    A bit more alchemy:

    fun Unit.get(message: String) { 
        print(message+" "); 
    print("Magic: ")["Alakazam"]["Abracadabra"]["Voila!"];

    I would like to go further and add invoke... But here Kotlin starts acting up, saying he expects function type, not Unit.

    But anyway we can extend Unit's functionality, creating almost... a real unit, in Pascal meaning of the word.

    Ok, then no more magic, just brute force: the nastiest Hello World ever:

    while (println("Hello, ") == println("world")) {}
    1. Inability to define invoke() for Unit seems to be bug. Please report it to the tracker.

  15. apparently, overloading for shift left "<<" and right ">>" is not supported yet.  any plan to support them in the future?

    1. We are not planning to support "<<" and ">>". Shift operations are available as named functions:

      1 shl 5 // = 32
  16. What about bit operators &, |, <<, <<<, >>, >>>

    1. They are there in the form of funcitons: and, or, shl, shr, ushr