Newsgroup: it.comp.java
Titolo: Ereditarietà

L'ereditarietà di metodi e variabili di classe è consentita?
Cioè, se io definisco:
class Myclass {
  static void metodo() {}
}
class Myclass2 extends Myclass {
     public static void main(String arg[]) {
               Myclass2.metodo();
}
}
è corretto o va contro la logica della OOP?
Un'altra cosa, la parola chiave super è un riferimento alla superclasse, ma
cosa significa veramente all'interno di un metodo. Cioè se io scrivo:
void metodo() {
       super.metodo();
}
devo interpretare la chiamata al metodo definito nella superclasse tramite
oggetto corrente o tramite superclasse(anche se mi sembra improbabile).
Saluti.
 

Quindi super. indica solamente al metodo chiamante di andare a ricercare la
definizione dello stesso nella supeclasse?
Ma è utilizzabile anche se non ho niente di ridefinito?
Grazie.

Grazie Scorpio.
Il mio libro liquidava la domanda in questione dicendo che l'ereditarietą
di metodi di classe non č definita dal linguaggio, ma precedentemente io
l'ho usata spesso e mi sono trovato un po' spaesato leggendo quello che
diceva.
Saluti.

 è corretto o va contro la logica della OOP?
E' corretto. Una sottoclasse eredita variabili e metodi di classe. In un
certo senso é logico, perché le "leggi dell'ereditarietà" dicono che una
sottoclasse é dello stesso tipo della superclasse.
Comunque i metodi statici sono da usare con grande prudenza e parsimonia,
perché é vero che si puo' infrangere la logica OOP. In particolare i metodi
statici ereditati non sono ridefinibili e il polimorfismo non funziona.
Per esempio:
class Myclass {
  static void metodo1() {System.out.println("A");}
  void metodo2() {metodo1();}
}
class Myclass2 extends Myclass {
    static void metodo1() {System.out.println("B");}
    public static void main(String arg[]) {
       /* test 1*/
       Myclass2 test1= new Myclass2();
       test1.metodo2();
       /* test 2 */
       Myclass test2 = new MyClass2();
       test2.metodo1();
    }
}
Nel test 1 l'instanza della sottoclasse chiama il metodo ereditato
metodo2(): il risultato sarà "A" perché metodo1() é statico, quindi il link
é fatto già alla compilazione. Se i metodo1() fossero stati non statici, il
risultato sarebbe stato ovviamente "B".
Nel test 2 si crea un'istanza della sottoclasse, ma la variabile é del tipo
della superclasse. Il risultato sarà ancora una volta "A" perché la versione
di metodo1() chiamata sarà quella specificata dal tipo della variabile, di
nuovo perché il link si effettua alla compilazione e non al runtime per i
metodi statici.
Spero di non essere stato troppo oscuro...
bye
Carlo

Scusa ma non capisco, come fai nell'esempio a chiamare il metodo statico
ereditato da Myclass su un'istanza di Myclass2: test2.metodo1() ? In teoria
questo dovrebbe dare errore in compilazione, o sbaglio? Ti avvertira' che stai
chiamando un metodo statico su di un'istanza...


 chiamando un metodo statico su di un'istanza...
Un metodo statico puo' essere invocato sia specificando la classe, sia
specificando un'instanza della classe. Chiaramente é altamente
sconsigliabile usare il secondo tipo di invocazione, perché puo' creare
confusione. Nella fattispece un codice come quello che ho usato é da evitare
perché piazzato in un codice di un certo spessore puo' indurre comportamenti
inaspettati e difficili da smascherare.
Ho dato questo esempio appunto per dimostrare quanto sia delicato usare i
metodi statici se non si fa attenzione. Generalmente i metodi statici sono
da limitare al massimo: in certi casi non se ne puo' fare a meno, ma sono
più rari di quello che si crede se si modellizza bene il problema.
Comunque capire l'esempio che ho dato é importante per capire il
funzionamento di static.
bye
Carlo


 Grazie.

Ma allora a cosa serve final nella dichiarazione di metodi di classe?
Non è raro vedere alcune cose tipo:
static final nomeMetodo ( )
{}
Saluti.
 

 tramite super.metodo().
Ho l'impressione tu non abbia ben capito la domanda di Francesco, allora mi
permetto di correggere.
Si puo' utilizzare super.metodo() in una sottoclasse, anche se questa non ha
ridefinito metodo(), ma ha lo stesso effetto di chiamare metodo()
direttamente poiché non c'é ambiguità possibile.
Quando instanzi una sottoclasse, un'instanza della superclasse viene pure
creata in memoria, "nascosta" all'interno della prima. Cosi' come this é una
referenza verso l'indirizzo memoria dell'instanza stessa, super é una
referenza verso l'indirizzo memoria dell'instanza nascosta della
superclasse. Cosi' con questa referenza é possibile chiamare i metodi della
superclasse.
Ancora una piccola precisazione: i metodi e le variabili private della
superclasse *sono* ereditati, ma restano inaccessibili direttamente.
Facciamo un esempio:
class Super {
    private String ciao;
    public setString(String s) {
        ciao = s;
    }
    public String getString() {
        return ciao;
    }
}
class Sub extends Super {
    public static void main(String[] args) {
        Sub sub = new Sub();
        sub.setString("Ciao");
        System.out.println(sub.getString());
    }
}
Dunque per accedere a variabili private della superclasse é necessario che
quest'ultima fornisca dei metodi d'accesso. E' un buon sistema se si crea
una classe destinata ad essere subclassata da altri programmatori:
l'implementazione della superclasse resta nascosta e un'eventuale modifica
non compromette il codice scritto dagli utilizzatori della classe.
bye
Carlo

Ammettendo  il caso che io abbia:
class A {
         static void metodo() {}
}
class B {
        void metodo2() {
          super.metodo();
    }
}
Anche se inutile in questo caso č possibile?
NB: il compilatore non restituisce errore alcuno.
Saluti.

Grazie a tutti, avete finalmente risolto l'altro mio problema.
Il mio libro - è ora che lo cambi - diceva che super era un riferimento
alla superclasse e non a un suo oggetto, quindi non riuscivo a capire come
un riferimento ad una classe potesse accedere ai membri istanza.
Ringrazio ancora tutti.

Ma quando viene creato l'oggetto riferito tramite super? Cioč se nella mia
sottoclasse io non definisco alcun oggetto della stessa ho cmq un oggetto
super?
Saluti.

 super?
Riprendiamo l'esempio:
class Super {
    private String ciao;
    public setString(String s) {
        ciao = s;
    }
    public String getString() {
        return ciao;
    }
}
class Sub extends Super {
    public Sub() {
        System.out.println("Costruttore di Sub");
    }
    public static void main(String[] args) {
        Sub sub = new Sub();
        sub.setString("Ciao");
        System.out.println(sub.getString());
    }
}
In Sub ho definito un costruttore semplice. Java automaticamente modifica il
costruttore cosi':
    public Sub() {
        super();
        System.out.println("Costruttore di Sub");
    }
Cioé viene chiamato il costruttore della superclasse.
D'altronde se avessi definito nella superclasse un costruttore con
parametri, il compilatore m'avrebbe costretto ad aggiungere esplicitamente
super(parametri).
Quindi se non crei un'instanza della sottoclasse, non si crea nemmeno una
"instanza" della superclasse.
Come sempre se ci sono variabili e metodi statici questi sono presenti, ma
non la referenza super perché necessita di un'istanza.
bye
Carlo