Java 8 "default method" versus C # "extend method"

9

Java 8 introduces the concept of "standard method" to allow adding new functionality to an interface.

C # provides "extension methods" that allow you to "add" methods (features) to existing types.

Considering how they are implemented by the language and the possible scenarios of use, in what aspects are they equivalent and in which they differ?

    
asked by anonymous 02.04.2016 / 01:05

2 answers

11

Alone the C # extension method is not equivalent to the standard Java method. Only when the interface is added does the mechanism be comparable.

It is now clear that in Java the syntax is more convenient.

Default method

The default Java method becomes part of the type. There is an inheritance from the interface method to the class method. Here are the same methods. The class pass have them inside them. Any kind of access to the class, even by reflection, will indicate their presence.

In this case, if the programmer does not want the default implementation, he can write his own one to fulfill that interface. If a class inherits from this class, the inherited implementation can write another implementation without problems.

It is clear that the method is virtual, as every method is in interface. It is a runtime mechanism according to the interface / class declaration. It has the advantages and disadvantages of that. The VM needs to handle the operation.

Extension Method

Even though it is on top of an interface and although it seems that a type that implements the interface has that method, the extension method remains static and totally out of type. By being static these methods work more like functions.

As the extension method has lower priority, this same effect will usually be obtained if the class implements the method declared in the interface, at any point in the hierarchy. But not polymorphically. It will only work if it is called by the specific type and the compiler knows what type it is. If the decision has to be dynamic, it will be transformed into static and will call the static extension method. You may end up calling what you should not or at least what the programmer does not expect.

I can not guarantee (I am not aware enough) that there are no extra specific cases where this can be a problem. One obvious is that it is easier to have name conflicts. Another is that it can give way to dangerous tricks.

Because the method is external to the type, it can not be accessed directly by type, it is independent and isolated.

This is a language feature and fully solved by the compiler as per the use of the method (as opposed to its declaration). The CLR does not even have to deal with this.

One advantage of extension methods (some people say is disadvantage) is that you can add new methods to an interface and make all classes that you propose to implement the interface already have the method. With the Java engine, you have to modify the interface to add the new method.

There is a proposal in C # to do something more similar to Java. There are more ambitious proposals for other mechanisms such as traits .

I tried to do the same example in Java and C # according to what each language provides:

Java

public class HelloWorld {
    public static void main(String args[]) {
        Veiculo veiculoT = new Veiculo();
        System.out.println("veiculoT");
        veiculoT.diagnostico();
        veiculoT.liga();
        Testador.teste(veiculoT);
        Financeiro.compra(veiculoT);
        System.out.println("---------------");
        Veiculo carro = new Carro();
        System.out.println("carro");
        carro.diagnostico();
        carro.liga();
        Testador.teste(carro);
        Financeiro.compra(carro);
        System.out.println("---------------");
        Carro carro2 = new Carro();
        System.out.println("carro2");
        carro2.diagnostico();
        carro2.liga();
        carro2.buzina();
        Testador.teste(carro2);
        Financeiro.compra(carro2);
    }
}

interface Funcionamento {
    default void liga() {
        System.out.println("Ligou!");
    }
    static void buzina() {
        System.out.println("Buzinou!");
    }
}

class Testador {
    public static void teste(Funcionamento veiculo) {
        System.out.println("Vai testar");
        veiculo.liga();
    }
}

class Financeiro {
    public static void compra(Veiculo veiculo) {
        System.out.println("Comprou N: " + veiculo.id);
        veiculo.diagnostico();
        veiculo.liga();
    }
}

class Veiculo implements Funcionamento {
    public int id = 1;
    public void diagnostico() {
        Funcionamento.super.liga();
        Funcionamento.buzina();
        liga();
        System.out.println("Tudo ok!");
    }
}

class Carro extends Veiculo {
    public void liga() {
        System.out.println("Vrom!");
    }
    public void buzina() {
        System.out.println("bi bi!");
    }
}

See running on CodingGround .

C #

using static System.Console;

public class HelloWorld {
    public static void Main() {
        Veiculo veiculoT = new Veiculo();
        WriteLine("veiculoT");
        veiculoT.diagnostico();
        veiculoT.liga();
        veiculoT.teste();
        veiculoT.compra();
        WriteLine("---------------");
        Veiculo carro = new Carro();
        WriteLine("carro");
        carro.diagnostico();
        carro.liga();
        carro.teste();
        carro.compra();
        WriteLine("---------------");
        Carro carro2 = new Carro();
        WriteLine("carro2");
        carro2.diagnostico();
        carro2.liga();
        carro2.buzina();
        carro2.teste();
        carro2.compra();
    }
}

interface IFuncionamento {
    void liga();
}

static class Funcionamento {
    public static void liga(this IFuncionamento func) {
        WriteLine("Ligou!");
    }
    public static void buzina() {
        WriteLine("Buzinou!");
    }
}

static class Testador {
    public static void teste(this IFuncionamento veiculo) {
        WriteLine("Vai testar");
        veiculo.liga();
    }
}

static class Financeiro {
    public static void compra(this Veiculo veiculo) {
        WriteLine("Comprou N: " + veiculo.id);
        veiculo.diagnostico();
        veiculo.liga();
    }
}

class Veiculo : IFuncionamento {
    public int id = 1;
    public void diagnostico() {
        Funcionamento.liga(this);
        Funcionamento.buzina();
        liga();
        WriteLine("Tudo ok!");
    }
    public virtual void liga() {
        Funcionamento.liga(this);
    }
}

class Carro : Veiculo {
    public override void liga() {
        WriteLine("Vrom!");
    }
    public void buzina() {
        WriteLine("bi bi!");
    }
}

See working on dotNetFiddle .

Note that calling external methods such as Teste() and Compra() can be called more conveniently in C #. But the Liga() method needs an extra class with extension method to contain the implementation. In addition you need to have an implementation in the concrete class, even if you only delegate to the extension method. Without this there is no polymorphism.

In C # this is a trick that induces errors and makes it difficult to debug and use reflection, which can bring unexpected results to the most naive programmer.

    
02.04.2016 / 02:02
0

I think it's different things.

C # has no default method as Java does not have extensions methods . What our friend did was an attempt to arrive at the same result. Of course this way is subject to errors because it tried to do something that in C # does not exist.

Extensions methods are great for organizing the code and have a fluent programming, except that it protects the internal elements of your class that will be extended, but in short, compare orange with apple.

    
03.10.2016 / 21:00