lunedì 23 settembre 2013

Q9


Given:
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
B.
cantering cantering cantering
C.
compilation fails
D.
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