Qual é a implementação “padrão” do método definido em uma Interface?

91

Na interface de coleção, encontrei um método chamado removeIf()que contém sua implementação.

default boolean removeIf(Predicate<? super E> filter) {
    Objects.requireNonNull(filter);  
    boolean removed = false;  
    final Iterator<E> each = iterator();   
    while (each.hasNext()) {  
        if (filter.test(each.next())) {  
            each.remove();  
            removed = true;  
        }  
    }  
    return removed;  
}  

Eu quero saber se existe alguma maneira de definir o corpo do método em uma interface?
Qual é a defaultpalavra - chave e como funciona?

gifpif
fonte
3
veja esta postagem sobre o padrão zeroturnaround.com/rebellabs/java-8-explained-default-methods/…
emeraldjava
Postagem relacionada stackoverflow.com/questions/31578427/…
Ravi,

Respostas:

162

De https://dzone.com/articles/interface-default-methods-java

Java 8 introduz o novo recurso “Método padrão” ou (métodos Defender), que permite ao desenvolvedor adicionar novos métodos às interfaces sem quebrar a implementação existente dessas interfaces. Ele fornece flexibilidade para permitir que a interface defina a implementação que será usada como padrão na situação em que uma classe concreta falha em fornecer uma implementação para aquele método.

public interface A {
    default void foo(){
       System.out.println("Calling A.foo()");
    }
}

public class ClassAB implements A {
}

Há uma pergunta comum que as pessoas fazem sobre os métodos padrão quando ouvem sobre o novo recurso pela primeira vez:

E se a classe implementar duas interfaces e ambas as interfaces definirem um método padrão com a mesma assinatura?

Exemplo para ilustrar esta situação:

public interface A {  
    default void foo(){  
        System.out.println("Calling A.foo()");  
    }  
}

public interface B {
    default void foo(){
        System.out.println("Calling B.foo()");
    }
}


public class ClassAB implements A, B {

}  

Este código falha ao compilar com o seguinte resultado:

java: class Clazz inherits unrelated defaults for foo() from types A and B

Para corrigir isso, em Clazz, temos que resolver isso manualmente, substituindo o método conflitante:

public class Clazz implements A, B {
    public void foo(){}
}

Mas e se quisermos chamar a implementação padrão do método foo () da interface A em vez de implementar a nossa própria.

É possível se referir a A # foo () da seguinte maneira:

public class Clazz implements A, B {
    public void foo(){
       A.super.foo();
    }
}
gifpif
fonte
18
Obrigado, exposição realmente boa. Você respondeu a todas as minhas perguntas antes que eu tivesse a chance de fazê-las.
Jeff Hutchins
por que não usar resumo em vez disso?
Astolfo Hoscher
1
@AstolfoHoscher Você só pode estender uma classe, mas pode implementar várias interfaces.
Charles Wood
49

Esses métodos são chamados de métodos padrão. O método padrão ou método Defender é um dos recursos recém-adicionados no Java 8.

Eles serão usados ​​para permitir que um método de interface forneça uma implementação usada como padrão no caso de uma classe concreta não fornecer uma implementação para aquele método.

Portanto, se você tiver uma interface, com um método padrão:

public interface Hello {
    default void sayHello() {
        System.out.println("Hello");
    }
}

A seguinte classe é perfeitamente válida:

public class HelloImpl implements Hello {

}

Se você criar uma instância de HelloImpl:

Hello hello = new HelloImpl();
hello.sayHello();  // This will invoke the default method in interface

Links Úteis:

Rohit Jain
fonte
Então está tudo bem se uma classe implementa uma interface e não implementa seu método? No que diz respeito ao Java7, que estou usando, isso não é permitido.
Aniket Thakur
2
@AniketThakur. Isso não é permitido antes do Java 8. Este recurso é adicionado no Java 8 apenas. Você pode evitar dar a implementação de métodos padrão em sua classe de implementação.
Rohit Jain de
1
@PawanMishra. Veja meu comentário anterior. Não, você não precisa fornecer implementação de métodos de interface padrão na implementação de classe.
Rohit Jain de
1
@PawanMishra, você pode substituí-lo. Não há nenhuma restrição, pois você precisa usar apenas a implementação padrão.
Aniket Thakur
4
Um passo à frente que finalmente evitará ficar confuso com a herança múltipla!
Xtreme Biker
17

Eu fiz um pouco de pesquisa e encontrei o seguinte. Espero que isto ajude.

Problema existente

Os métodos de interface normais são declarados como abstratos e devem ser definidos na classe que implementa a interface. Isso 'sobrecarrega' o implementador da classe com a responsabilidade de implementar todos os métodos declarados. Mais importante, isso também significa que estender uma interface não é possível após a 'publicação'. Caso contrário, todos os implementadores teriam que adaptar sua implementação, interrompendo a compatibilidade de origem e binária com versões anteriores.

Solução adotada em Java 8

Para lidar com esses problemas, um dos novos recursos do JDK 8 é a possibilidade de estender as interfaces existentes com métodos padrão. Os métodos padrão não são apenas declarados, mas também definidos na interface.

Pontos importantes a serem observados

  1. Os implementadores podem escolher não implementar métodos padrão na classe de implementação.
  2. Os implementadores ainda podem sobrescrever métodos padrão, como métodos de classe não finais regulares podem ser sobrescritos em subclasses.
  3. Classes abstratas podem até mesmo (re) declarar métodos padrão como abstratos, forçando as subclasses a reimplementar o método (às vezes chamado de 're-abstração').
Aniket Thakur
fonte