1

I'm writing Kotlin code and one the features it has is extension methods, which are effectively the same as normal functions except the syntax you use looks like an instance method call.

Normal function

fun blah(x: Int) { println(x) }
val f = blah(1)

Extension method

fun Int.blah() { println(this) }
val f = 1.blah()

As far as I understand, C# extension methods work similarly.

In principle, literally any non-nullary function could be written as an extension method by moving the type of the first parameter to the left of the function name and adjusting the function body and call sites accordingly (as in this example).

Should I write all my functions as extension methods, then? None of them? What principle should I use to decide what functions to write normally, and which to write as an extension method of one of the inputs?

Jesse
  • 6,725
  • 5
  • 40
  • 45
  • In general, IMO, u should avoid extending objects you don't own – Marcus Höglund Oct 27 '17 at 06:26
  • @AlexeiLevenkov That's about extension method vs inheritance. I'm asking about extension method vs normal function/static method. – Jesse Oct 27 '17 at 06:31
  • 1
    @MarcusHöglund Why do you think that? You can scope your extension functions. They aren't global. In my opinion, writing extensions on classes you don't own is one of the best use cases for extension functions. It let's you write readable DSLs. – marstran Oct 27 '17 at 08:55

3 Answers3

1

https://kotlinlang.org/docs/reference/extensions.html#extensions-are-resolved-statically

Extensions are resolved statically

Extensions do not actually modify classes they extend. By defining an extension, you do not insert new members into a class, but merely make new functions callable with the dot-notation on variables of this type.

We would like to emphasize that extension functions are dispatched statically, i.e. they are not virtual by receiver type

So writing all of your functions as extension methods wouldn't be a good approach because they are dispatched statically. This takes away the ability to override them e.g. in derived classes.

It is more like a design choice when you make a extension function or a "normal" function.

I would recommend you the following: Whenever you have a function which you would write as an Utility-function with an Utility-class like StringUtil.isNullOrEmpty(String), use extension functions. Use the rest as "normal" functions.

Also read the Kotlin's motivation to create Extensions: https://kotlinlang.org/docs/reference/extensions.html#motivation

guenhter
  • 11,255
  • 3
  • 35
  • 66
  • 1
    This is true for OOP but for example, IEnumerable is based on [functional programming principles](https://blogs.msdn.microsoft.com/ericlippert/2009/05/18/foreach-vs-foreach/) and in that case it's completely fine to have static methods. – CookedCthulhu Oct 27 '17 at 07:57
  • 1
    Agree. I there is no yes/no list when you should use extension methods. There are situations (like the one you described), where you more or less have to use it, and others where you shouldn not use it. – guenhter Oct 27 '17 at 08:11
0

You write extensions when you do not have access of source code. In Java, you write utility classes.

public final class BarUtility {
    public static int foo(Bar i, int j){
        return i.value + j;
    }
}

BarUtility.foo(bar, 1);

In Kotlin, you write extensions method.

fun Bar.foo(i: Int): Int = value + i
bar.foo(1)

In C#, it is the same but you also use it for interface method implementation. (Kotlin allows interface method implementation.)

Joshua
  • 5,901
  • 2
  • 32
  • 52
0

There is no fixed rule, but you shouldn't write all of your normal functions as extension methods.

They are primarily used for two things:

Extending types that you don't have direct control over. A common example in C# is the ForEach() function that extends IEnumerable (basic types for lists etc.) with a method to apply an action to all items:

public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
     foreach (T item in enumeration)
     {
        action(item);
     }
}

Helper functions that simplify common calls to your own classes, but don't warrant an own method in your class or you don't want be part of your API.

Lennart
  • 9,657
  • 16
  • 68
  • 84