Given:
interface Rideable {
interface Rideable {
String ride();
}
class Horse implements Rideable {
String ride() {
return "cantering
";
}
}
class Icelandic extends Horse {
String ride() {
return "tolting
";
}
}
class Test {
public static void main(String[] args) {
Rideable r1 = new Icelandic();
Rideable r2 = new Horse();
Horse h1 = new Icelandic();
System.out.println(r1.ride() +
r2.ride() + h1.ride());
}
}
What is the
result?
A.
tolting cantering cantering
tolting cantering cantering
B.
cantering cantering cantering
cantering cantering cantering
C.
compilation fails
compilation fails
D.
an exception is thrown at runtime
an exception is thrown at runtime
Risposta C.
Tutti i metodi di una interfaccia
sono automaticamente pubblici. I metodi ride() delle classi Horse e Icelandic
sono invece dichiarati default , infatti non hanno modificatore.
Perciò i metodi ride() di Horse e Icelandic
abbassano la visibilità del metodo ride() di Rideable.
Questo in Java e in generale nella
programmazione ad oggetti non è permesso perché viola il principio di Principio
di Liskov, che pretende la sostituibilità tra una superclasse (in questo caso
un’interfaccia) e una sottoclasse.
Questo è esplicitamente scritto
nella documentazione ufficiale del Java :
The access
modifier (§6.6) of an overriding or hiding method must provide at least as much
access as the overridden or hidden method, or a compile-time error occurs. In
more detail:
·
If the overridden or hidden method is public, then the
overriding or hiding method must be public; otherwise, a compile-time error
occurs.
·
If the overridden or hidden method is protected, then
the overriding or hiding method must be protected or public; otherwise, a
compile-time error occurs.
·
If the overridden or hidden method has default
(package) access, then the overriding or hiding method must not be private;
otherwise, a compile-time error occurs.
Per capire questo concetto si prenda
questo esempio :
class A {
public void myMethod() {...}
}
class B extends A {
private void myMethod() {...}
}
//...
A a = new B();
Istanziare una variabile di tipo
A assegnandole un oggetto di tipo B è sempre possibile in Java, e su questo si
basa l’ereditarietà. Ma al momento di usare il metodo myMethod() sorgono i
problemi di visibilità perché il metodo è pubblico in A ma in realtà è la
variabile è un oggetto di tipo B e B non ha il metodo pubblico.
Riferimenti:
Nessun commento:
Posta un commento