Hola Mario
Siguiendo tu cita
En relación a la pregunta c1), tener en cuenta que los objetos pueden tener un tipo estático definido por una interface, pero no un tipo dinámico (es decir, no se puede usar new sobre un tipo definido por una interface porque son definiciones abstractas sin constructor).
Yo, pasaba por alto que un objeto se puede declarar perteneciente a una interface, independientemente de como se inicialize.
Después de leer tu cita, recuerdo haberlo visto en otros ejercicios y para más inri se comentaba en la lección de este ejercicio.
Podemos declarar variables del tipo interfaz, pero para inicializarlas utilizaremos una clase concreta que lo implemente. Por ejemplo List <String> miLista; declara una variable con el tipo de la interface List. La inicialización miLista = new List<String>(); no es posible porque no se puede crear un objeto del tipo definido por una interfaz. En cambio miLista = new LinkedList<String> (); sí es válido.
Es decir que me fui directo p'al toro sin encomendarme a nadie.
Ahora, siguiendo tus indicaciones (a veces lo hago por mi cuenta) he creado las clases 'las incluyo en este mensaje' y en la clase con main he creado tres objetos:
Interface1 miVar1 = new Clase1();
Interface1 miVar2 = new Clase2();
Clase2 miVar22 = new Clase2();
Estas tres instrucciones no dan error
Del primer objeto 'miVar1' puedo invocar los métodos de su propia clase sin problema (Ver clase Test con main)
Del objeto 'miVar2' puedo invocar los métodos que hereda de Clase1, pero no los de su clase (la Clase2)
Al definir el objeto perteneciente a 'interface1' delimita que métodos tendrá diponibles.
Todo lo que hereda de 'Clase1' está disponible
Como la 'Clase2' no implementa la 'interface1', este objeto 'miVar2' no tiene acceso a los métodos de la 'Clase2'
Finalmente el objeto 'miVar22' declarado e inicializado perteneciente a la clase 'Clase2' no tiene ningún problema en acceder a los métodos de su clase (el método getNombre() pertenece a la 'Clase2') ni a los métodos que hereda de 'Clase1' (el método propietario() pertenece a la clase 'Clase1')
Mi resumen.
Aunque la Clase2 disfruta de los métodos que hereda de Clase1.
¿Porque crear la Clase2 que tendrá sus propios métodos y usarla en el entorno de la Interface1 que no implementa y donde no podrá disfrutar de sus propios métodos?
No tiene sentido, es complicarse la vida.
Solución.
En lugar de usar la Clase2, usar la Clase1.
O bien, implementar Interface1 en Clase2 y se tendrá acceso a los métodos propios de Clase2.
Interface1
public interface Interface1 {
String propietario();
}
Clase1
public class Clase1 implements Interface1 {
@Override
public String propietario() {
return "\"Clase propietaria - " + this.getClass() + "\" -> Valor devuelto por el método 'propietario()' de la clase 'Clase1'.";
}
} // Fin de la clase Clase1
Clase2
public class Clase2 extends Clase1 {
private String nombre;
public Clase2() { // Inicializa atributos
this.nombre = "\"Clase propietaria - " + this.getClass() + "\" -> Valor inicializado en el 'constructor' de la clase 'Clase2'.";
}
public String getNombre() { return nombre; }
} // Fin de la clase Clase2
Test
public class Test {
public static void main(String [] args) {
System.out.println("\fPrueba1");
Interface1 miVar1 = new Clase1();
System.out.println("\n\tmiVar1.propietario()=\n"+miVar1.propietario());
Interface1 miVar2 = new Clase2();
System.out.println("\n\tmiVar2.propietario()=\n"+miVar2.propietario()); // este método se hereda de Clase1
//La siguiente instrucción da error. No encuentra el metodo getNombre
// System.out.println(miVar2.getNombre());
System.out.println("\n\tmiVar2.getNombre()=\nDa el error (cannot find symbol - method getNombre())");
Clase2 miVar22 = new Clase2();
System.out.println("\n\tmiVar22.propietario()=\n"+miVar22.propietario()); // este método se hereda de Clase1
System.out.println("\n\tmiVar22.getNombre()=\n"+miVar22.getNombre());
}
} // Fin de la clase Test
Saludos.