Dato questo codice Java, questo uscite 0 e 4:Il costruttore Java non è così intuitivo. O forse non è Java, è C# che non è intuitivo
class A{
A() { print(); }
void print() { System.out.println("A"); }
}
class B extends A{
int i = Math.round(3.5f);
public static void main(String[] args){
A a = new B();
a.print();
}
void print() { System.out.println(i); }
}
E con questo codice identico C#, questo emette 4 e 4
using System;
class A{
internal A() { print(); }
virtual internal void print() { Console.WriteLine("A"); }
}
class B : A{
int i = (int) Math.Round(3.5f);
public static void Main(string[] args){
A a = new B();
a.print();
}
override internal void print() { Console.WriteLine(i); }
}
Anche se calcoliamo che l'uscita dovrebbe essere 4 e 4 su Java, ma la risposta è in realtà 0 e 4 su Java. Poi ho provato in C#, la risposta è 4 e 4
Che cosa dà? Java razionale è, durante la costruzione di B, A è ancora in fase di inizializzazione (di conseguenza, suppongo che B stia ancora inizializzando se Java ha detto che A è ancora in fase di inizializzazione), quindi il valore predefinito dovrebbe essere 0. Quindi l'output è 0 e 4 in Java.
Perché il comportamento del costruttore C# differisce da Java o viceversa?
Farò in modo che altre persone rispondano al "perché", ma questo tipo di problemi è il motivo per cui in genere è considerata una cattiva pratica chiamare i metodi virtuali dai costruttori. –
+1 per considerare di chiamare un metodo virtuale da costruttore una pratica scadente. L'output non è prevedibile dato che diverse lingue hanno una diversa filosofia di progettazione – Hao
@HovercraftFullOfEels Lo sento anch'io. Volevo trovare una soluzione però. Come rendere più chiaro l'intento del codice o il comportamento del codice, date le sfumature delle lingue. Potrebbe non esserci una soluzione chiara a questo problema, ma forse ci sono alcune buone pratiche in giro, ad es. considerando che il metodo virtuale non dovrebbe essere chiamato nel costruttore – Hao