2011-12-07 17 views
12

si lanzamos un objeto a una interfaz, ¿no podrá este objeto llamar a sus propios métodos? en el siguiente ejemplo, myObj solo podrá llamar a los métodos MyInterface?lanzar un objeto a una interfaz en java?

MyInterface myObj = new Obj(); 

Si esto es correcto, ¿cuál es la diferencia entre los 2 objetos:

MyInterface myObj = new Obj(); 

MyInterface mySec = new Sec(); 

Gracias por su ayuda

+0

[this] (http://docs.oracle.com/javase/tutorial/java/concepts/interface.html) podría ser de ayuda. – Nerdtron

Respuesta

16
MyInterface myObj = new Obj(); 
MyInterface mySec = new Sec(); 

Para que esto sea legal, tanto Obj y Sec se tiene que ser implementadores de MyInterface. La diferencia entre estos dos objetos sería cómo proporcionan esa implementación. Obj y Sec podrían hacer dos cosas muy diferentes o muy similares, pero su punto en común es que cumplirían un contrato en el que podrían confiar. Considere usted tiene un método

public void doSomethingWith(MyInterface thing) { 
    thing.frob(); 
} 

Cada objeto, myObj y mySec, se podría pasar en este método, y este método podría utilizar frob método de ese objeto (FROB suponiendo que es parte de la declaración de interfaz). Esto es que libera. Esto le permite hacer cosas muy potentes, programando interfaces y no implementaciones. Por ejemplo, puede ampliar la funcionalidad de las clases y no cambiar una línea de código en esas clases, simplemente pasa una implementación diferente de una dependencia. No está vinculado a, o junto con, cualquier implementación dentro del método doSomethingWith.

pero también leí que si declaramos los myObj de objeto como MyInterface, myObj no será capaz de utilizar sus propios métodos (de la clase Obj), es que corregir

Internamente , las instancias de Obj continuarán teniendo acceso completo a la API Obj. myObj sigue siendo Obj, siempre podrá usar sus propios detalles de implementación.

public interface MyInterface { 
    void frob(); 
} 

public class Obj implements MyInterface { 

    public void frob() { 
     doFrobbing(); 
    } 

    private void doFrobbing() { 
     System.out.println("frobbing"); 
    } 

    public static void main(String[] args) { 
     MyInterface myObj = new Obj(); 
     myObj.frob(); // still internally calls doFrobbing() 
     ((Obj)myObj).doFrobbing(); // visible only via class reference 
    } 
} 

Las instancias de Obj todavía serán instancias de Obj, y aquellos casos todavía será capaz de utilizar doFrobbing. Externamente, las personas usando esas instancias a través de la referencia de interfaz solo podrán acceder a los métodos de interfaz.

+0

gracias a anthony por esta gran explicación, lo entiendo, y aún más gracias, pero también leí que si declaramos el objeto 'myObj' como MyInterface,' myObj' no podrá usar sus propios métodos (del clase 'Obj'), ¿es correcto? – Paul

+0

@Paul, buena pregunta, respuesta actualizada. –

+0

gracias por la actualización, ¿cuál es el punto de hacer esto? (Ocultando los métodos de 'Obj' cuando' MyInterface' es el tipo) Existe una interfaz para "agregar" algunos métodos a un objeto, ¿verdad ?, entonces, ¿por qué oculta los otros métodos? (o tal vez no hay razones para eso, esto funciona porque, como regla general en todos los lenguajes de programación, un "tipo" funciona así?) – Paul

1

Solo los métodos en la interfaz son visibles, pero todos los métodos en el objeto aún pueden invocarse, siempre que se acceda de otra forma. Por ejemplo:

public interface MyInterface { 
    String getName(); 
} 

public class Obj implements MyInterface { 
    private String getFirstName() { 
     return "John"; 
    } 

    private String getLastName() { 
     return "Doe"; 
    } 

    @Override 
    public String getName() { 
     return getFirstName() + " " + getLastName(); 
    } 
} 

public class Sec implements MyInterface { 
    private String getDate() { 
     return new Date().toString(); 
    } 

    @Override 
    public String getName() { 
     return getDate(); 
    } 
} 

En los casos anteriores, tanto Obj y Sec pueden llamar a sus miembros privados, a pesar de que no serán visibles en otras clases. Entonces cuando dices ...

MyInterface myObj = new Obj(); 
MyInterface mySec = new Sec(); 

...como ha preguntado en la pregunta, si bien es cierto que en myObj y mySec el único método visible es getName(), su implementación subyacente puede ser diferente.

+0

gracias a jonathan por esta gran explicación, mmh, vale, la entiendo un poco más, entonces si los métodos de 'Obj' no son visibles para otras clases, ¿en qué caso? (¿Tiene un ejemplo simple?) – Paul

+0

Lo siento, no estoy seguro de entender su pregunta. –

1

No hay diferencia. Solo podrá invocar los métodos de interfaz MyInterface en myObj y mySec. Obviamente, su código solo se compilará si ambos Obj y Sec implementan la interfaz Myinterface.

+0

gracias por su respuesta rápida, entonces esta es la cuestión: ¿y si comenzamos el proyecto sin interfaces, y luego queremos implementar una interfaz porque necesitamos más métodos para agregar en las clases 'A' y' B': perderemos los métodos previos de 'A' y' B' porque declararemos 'a' y' b' como objetos de I ... – Paul

+0

@Paul Las interfaces existen con el propósito de agregar alguna * interfaz * común (o en otras palabras, un contrato) a diferentes clases y dejando que esas clases realmente implementen la * funcionalidad * de acuerdo con el contrato. En realidad, no está obligado a utilizar interfaces si desea agregar nuevos métodos a una clase. Aquí hay una definición simple de lo que es una interfaz: http://docs.oracle.com/javase/tutorial/java/concepts/interface.html – Strelok

+0

gracias Strelok, mi malentendido se trata de cambiar el "Tipo" de un objeto, y pongo la interfaz como el "Tipo", esto significaría que los métodos del obj ya no son "visibles" ... lo cual me confunde un poco. Aunque tengo el principio de las interfaces, entiendo que las interfaces son algunos métodos que compartirán 2 clases, pero lo que no estoy seguro de entender es: si "Interface" es el tipo, los otros métodos de la clase myObj ganaron ya no se puede ver – Paul

0

En el código que demostró que nunca realiza ningún molde.

Un uso típico de una interfaz es definir algunos métodos que estarán disponibles, sin importar la implementación concreta.

Un buen ejemplo de esto son los oyentes en el estándar JDK. Por ejemplo, el PropertyChangeListener. Esta es una interfaz que define un método que se puede invocar cuando 'se cambia una propiedad'. Un uso típico de esta interfaz es adjuntarla a una clase que tenga propiedades, y esta clase advertirá a los oyentes cuando una de sus propiedades haya cambiado.

A la clase no le importa lo que harán los oyentes. Solo se basa en el hecho de que este método propertyChange estará presente y llama a ese método.

La clase solo puede llamar a este método en el oyente, ya que solo conoce el método definido en la interfaz. Si esos oyentes tienen otros métodos, pueden llamar a esos mismos métodos, pero eso es solo porque saben que son más que la interfaz.

0
MyInterface mi = new Obj(); 
mi.getInterfaceMethods(); (methods in the MyInterface) 

if(mi instanceof Obj) { 
    mi.getObjMethods(); (methods in the Obj) 
} 
0

Cambiar el tipo de una variable (es decir, una referencia) no cambia el objeto en sí. Un objeto siempre puede llamar a sus propios métodos, sin importar cuáles sean los tipos de variables declaradas que hacen referencia a él.

1
MyInterface myObj = new Obj(); 
MyInterface mySec = new Sec(); 

Declara una instancia de MyInterface denominada myObj. Inicialízalo con Obj nuevo(); que está autorizado por el compilador si Obj implementa MyInterface. myObj solo puede llamar a los métodos MyInterface obviamente. Lo mismo para la segunda línea.

Aquí hay un código de ejemplo para probar:

public class Test { 

    public static void main(String args[]){ 
      A a = new A(); 
      a.say(); 
      a.a(); 

      B b = new B(); 
      b.say(); 
      b.b(); 

      I ia = new A(); 
      ia.say(); 
      ia.a(); // fail 
    } 

} 

interface i { 
    public void say(); 
} 

class A implements i { 
    public void say(){ 
     System.out.println("class A"); 
    } 
    public void a(){ 
     System.out.println("method a"); 
    } 
} 

class B implements i { 
    public void say(){ 
     System.out.println("class B"); 
    } 
    public void b(){ 
     System.out.println("method b"); 
    } 
} 
+0

gracias kbdjockey por su respuesta: está bien, pero ¿y si comenzamos el proyecto sin interfaces, y luego queremos implementar una interfaz porque necesitamos más métodos para agregar en las clases 'A' y' B': perderemos los métodos previos de 'A' y' B' porque declararemos 'a' y' b' como objetos de I ... – Paul

+0

El hecho de que 'A' y' B' implementen 'I' no significa que tiene que crear una instancia de ellos como tal. Todavía puede decir 'A myObj = new A()', y acceder a todos los métodos de 'A' (incluidos los reemplazados de' I'). –

0

Una simple analogía:

Considere un chef (interfaz). Y hay un chef chino (clases) y un chef estadounidense (clases). Ahora, hay un hotel con vistas a contratar un chef en base a unos criterios de elegibilidad como

  • puede cocinar para no vegetariano
  • puede cocinar vegetariano
  • tienen la experiencia de 5 años

Aquí, la elegibilidad es el contexto dentro del cual se evalúa la persona de tipo Chef (funcionalidad de los tipos). Ahora, puede haber casos en que el chef chino también pueda cocinar mariscos, platos italianos, etc., así podría ser el caso con su contraparte estadounidense. Todo esto puede parecer irrelevante para el gerente del hotel ya que solo le preocupan los criterios requeridos.

Los chefs que trabajan en un hotel son análogos al objeto de tipo Chef utilizado en el código. El trabajo obvio sería cocinar alimentos vegetarianos y no vegetarianos (criterios o métodos de interfaz). Eso no significa que el hotel no pueda utilizar las habilidades de fabricación de alimentos marinos del chef chino.

Es solo una cuestión de especificar qué habilidades (funcionalidad) el Hotel está buscando.

Espero que entiendas la idea.

Cuestiones relacionadas