Uma Legal sobre intefaces

Essa questão é na verdade um pega, pois a maioria conhece esta regra soh que esquecem de aplicá-la, vamos lá :

interface I{
    void metodo();
}

class Base{
    void metodo(){
         System.out.println("Base");
    }
}

public class MyClass extends Base implements I {
     void metodo(){
         System.out.println( "Subclass");    
     }
     public static void main( String [] args )
     {
         new MyClass().metodo();
     }
}    

Isso compila ?
Se sim, o que imprime ?

 Divirtam-se

Claudio Gualberto.

Na minha opinião compila e imprime “Subclass”.

Quando usamos uma Interface temos que escrever todos os métodos dela, neste caso apenas o metodo “Metodo”, mas quando escevemos este método para satisfazer a interface estamos sobreescrevendo o metodo “Metodo” do classe pai Base, por isso tudo que tem em Metodo da classe pai Base é descartado pq foi substituido.

Tô certo?

se tiver tudo no mesmo arquivo, nao compila…

nao se pode ter uma classe publica e uma interface ao mesmo tempo no mesmo .java

javac MyClass.java
MyClass.java:12: metodo() in MyClass cannot implement metodo() in I; attempting
to assign weaker access privileges; was public
void metodo(){
     ^
1 error

Um método sobrescrito não pode ser mais restrito do que o método que ele está tentando sobrescrever.
Quanto à interface e a classe no mesmo arquivo, apenas a classe tem modificador de acesso público, a interface é default, por isso não há problema.

Nota importante: JLS 9.1.4 - All interface members are implicitly public

Perai, viajei, oq aconteceu, pq o erro???

Todos os métodos definidos em uma interface são implicitamente public, quer você declare-os como public ou sem nenhum modificador de acesso.
Assim, o método metodo() definido na interface I é público.
Uma das regras do “overriding” é que o método que está tentando sobrescrever não pode ser mais restritivo (menos público?) do que o método que ele está sobrescrevendo. No nosso exemplo, o metodo metodo() em MyClass tem como modificador de acesso default, já que nenhum modificador foi definido para ele explicitamente.
default é mais restritivo do que public (e como!), daí o erro indicado.
Melhorou ou piorou? :stuck_out_tongue:

entendi, e como resolver uma situação dessas?

Tem q mudar a classe Base?!?

uma das maneiras é consertar o erro apontado pelo compilador, isto é, definir metodo() em MyClass como public, aí compila e o na hora de rodar imprime Subclass

pq ele sobrescreve void metodo(); da interface e naum da classe Base?

Essa realmente pega todo mundo…

Toda JavaInterface tem modificador de métodos public e na implementação na classe concreta, o modificador não pode ser menos restritivo…

Ou seja, public na interface, public na classe… Nenhum modificador na interface, public na classe…

Bom estudo a todos…

Tem haver com a “obrigatoriedade” de implementacao estipulada pela inteface???

Sim… Obrigatório…

Não faz sentido na Orientação á Objetos, dentro do conceito de Interfaces, ter serviços que não podem ser usados.

Entendeu?

Uma coisa…

Pq devemos ter sempre somente uma classe public ou interface public em um .java?

Por exemplo:

interface Mamifero
{
public abstract void Cachorro();
}

interface Aquatico
{
public abstract void Peixe();
}

interface Ar
{
public abstract void Canario();
}

class Pai implements Mamifero, Ar
{
public void Cachorro()
{
System.out.println(“Chama PAI de cachorro”);
}

public void Canario()
{
	System.out.println("Chama PAI de canário");
}

}

class Filho extends Pai
{
public void Cachorro()
{
System.out.println(“Chama FILHO de cachorro”);
}

public void Canario()
{
	System.out.println("Chama FILHO de canário");
}

}

class Main
{
public static void main( String []args )
{
Pai pai = new Filho();
pai.Cachorro();
pai.Canario();
}
}

O programa acima funciona legal, porém se eu mudar a classe Pai, por exemplo para public, já da erro. Pq, já que no arquivo há somente um public e interface é default?

interface Mamifero
{
public abstract void Cachorro();
}

interface Aquatico
{
public abstract void Peixe();
}

interface Ar
{
public abstract void Canario();
}

public class Pai implements Mamifero, Ar
{
public void Cachorro()
{
System.out.println(“Chama PAI de cachorro”);
}

public void Canario()
{
	System.out.println("Chama PAI de canário");
}

}

class Filho extends Pai
{
public void Cachorro()
{
System.out.println(“Chama FILHO de cachorro”);
}

public void Canario()
{
	System.out.println("Chama FILHO de canário");
}

}

class Main
{
public static void main( String []args )
{
Pai pai = new Filho();
pai.Cachorro();
pai.Canario();
}
}

[quote=CLAUDIO GUALBERTO]Essa questão é na verdade um pega, pois a maioria conhece esta regra soh que esquecem de aplicá-la, vamos lá :

interface I{
    void metodo();
}

class Base{
    void metodo(){
         System.out.println("Base");
    }
}

public class MyClass extends Base implements I {
     void metodo(){
         System.out.println( "Subclass");    
     }
     public static void main( String [] args )
     {
         new MyClass().metodo();
     }
}    

Isso compila ?
Se sim, o que imprime ?

 Divirtam-se

Claudio Gualberto.[/quote]

Kra ta implementando a interface então a classe concreta MyClass tem que subscrever o método como public. Não acredito que possa acontecer outro erro fora esse de jeito nenhum. Se vc subscrever o método como public void metodo(){} vc não vai tar subscrevendo o método da classe Base vai tar subscrevendo o método da interface que é obrigatório já que a classe não é abstract.

Quando uma classe implementa uma interface, você faz um CONTRATO e é obrigado à desenvolver os métodos dentro dela. (nesse problema ele obedeceu essa regra)

A questão de você estar criando uma interface, já faz os métodos serem public e abstract(você não precisa colocar isso, mas se colocar o efeito é o mesmo). E como você não pode diminuir o acesso do método, TODOS métodos do “contrato” da classe contratante(eita) devem ser declarados public então. (o método na classe não é declarado public e ai está o erro)

kd o public na implementacao do metodo da interface na classe?

vc pode ocultar public na interface porem qdo implementar vc deve colocar o public… isso pela simples regra que vc nao pode converter de um maior para menor ou seja, vc nao pode dizer que algo é public e vai ser private, por exemplo… mais vc pode dizer que um metodo protected vai ser public na subclasse!

E nesse caso o metodo observe que o metodo da class nao tem modificador de acesso entao é default e o da interface é public implicitamente… e isso nao dar para sobrescrever de acordo com que falei acima…

Esse assunto está no capitulo 1 ou é o 2 do livro da kathy… :smiley:

Eu ainda não sei o pq de ter sempre apenas uma classe public em um .java, mesmo sem haver derivação ou qualquer outro! Alguém sabe?

EU acertei mas isso é meio chato mesmo :slight_smile:

Sua pergunta não é mais uma questão técnica. Vamos discutir um pouco de OO.
Dentroa da POO (Programação Orientada a Objetos) temos os seguintes pilares que DEFINEM um sistema/componente/whatever como ORIENTADO A OBJETOS: reutilização, encapsulamento, herança, polimorfismo e abstração.

Reutilização significa que você pode pegar um componente do seu sistema e reutilizá-lo em qualquer outro sistema. É uma peça independente com uma funcionalidade definida através de seus MÉTODOS, que são os pontos de entradas, os fornecedores de serviço, do seu objeto. Reutilizar é pegar um arquivo COMPILADO (.jar, .class, .ear) e conseguir usar as suas funções.

Uma classe pública é uma classe que fornece alguma funcionalidade que pode ser utilizada por qualquer outro componente. As classes ficam armazenado em 1 arquivo .class no java, que pode ter mais de 1 classe nele.
Vamos imaginar que você tenha um mesmo componente (.class) que tenha duas classes públicas, ou seja, duas classes que tem uma funcionalidade bem definida e fornecem serviços para outras classes. Digamos agora que uma dessas classes você pode usar em outro sistema ou até mesmo precise ser substituído. Se no seu .class você tem duas classes INDEPENDENTES, que cada uma presta seus serviços, você terá de indisponibilizar uma das classe para substituir a outra, ou então levar uma classe inútil junto com outra que tem utilidade. Isso acaba com o princípio de reusabilidade do seu componente orientado a objeto.

Java é fortemente calcada na orientação a objetos. Por isso que na menor unidade que contém código do Java (o .class) você só pode ter uma classe que é a disponiblizadora de serviços. Se você tiver outras classes dentro dessa unidade, elas só tem razão de estarem lá se forem úteis apenas dentro daquele contexto, da mesma forma que disponibilizar uma classe que não pode ser reusável por depender diretamente de outras também é um erro, a não ser que ela esteja sendo disponibilizada dentro de um pacote, e seu acesso seja restrito à ele.

Um bom livro de referência sobre Orientação à Objeto é o “Engenharia de Software”, do Pressman. Lá você você entender todos os princípios da Orientação a Objetos e daí vai entender porque muita coisa no Java é do jeito que é.

Best Regards…

Obrigado pela explicação. Mesmo a minha dúvida sendo básica, não tenho problemas com OO. Era só uma dúvida que um dia apontou…rsrs…

By the way…foi bem clara a explicação…