Java: "Downcasting" a nuovo oggetto / opposto della taglio
Domanda
Scusa, non so davvero come fare un titolo per quella domanda; Forse c'è un nome per quello che sto cercando di fare che non lo so, ma posso spiegarlo con un po 'di codice:
Immagino che tu abbia una lezione che purtroppo né ha un costruttore di copie né un metodo di copia statica pubblica.
class A
{
private int i; // <- private, cant access
String x; // <- even worse: cant access unless in same pkg!
/* … other stuff, ctor, etc. … */
public A clone()
{
A a = new A();
a.i = i;
a.x = x;
return x;
}
}
Indovina ulteriormente, c'è qualche funzione che restituisce un oggetto di quella classe:
public static A someFn(x,y,z);
Ora il problema: voglio derivare da quella classe per aggiungere alcune funzionalità. Sfortunatamente, non ho né una dimensione di Java né un metodo CC o di copia statica.
Quindi quando faccio un
class B extends A
{
protected w;
public B clone()
{
/* as usual */
}
}
Quindi posso clonare la mia B e ottenerne una nuova, ma come posso convertire il restituito A da qualchefn () in un B. c'è comunque per fare il contrario di tagliare a Java? Se lo clone, è ancora una A e non posso copiarlo sul campo per campo. Questo è tutto semplice in C ++, ma come farlo in Java?
Soluzione 4
Sfortunatamente, l'unico modo a sinistra era un involucro completo che imitava la funzionalità di cui avevo bisogno, acquistato con un po 'di sovraccarico di prestazioni.
È completamente stupido che non ci sia modo di fornire una lezione in cui clone in ...
Altri suggerimenti
O cambia il design di A e B per essere in grado di trasformare una A in una B (se è anche significativo: come trasformeresti un cane in un dalmata?) O Utilizzare la composizione invece dell'eredità:
public class B {
private A a;
private int w;
public B(A a, int w) {
this.a = a;
this.w = w;
}
public int foo() {
return a.foo();
}
// ...
}
In Java, non si implementa clone()
Utilizzo dell'operatore new
. Spero che tu abbia il controllo della classe Java originale - non aderisce alle migliori pratiche.
Chiami super.clone()
invece che restituisce magicamente un oggetto del tipo corretto, con i risultati dei precedenti metodi cloni applicati ad esso.
Innanzitutto, il tuo metodo clone è sbagliato. Sarebbe qualcosa di simile:
public A clone(){
A result = (A)super.clone();
result.i = i;
result.x = x;
return result;
}
Mentre il clone per b:
public B clone(){
B result = (B)super.clone():
result.w = w;
return result;
}
Potresti avere un costruttore in B che prende un'istanza di A, estrae i dati richiesti da quell'istanza di A e crea l'oggetto B con esso.
Quindi, potresti chiamare un po'fn (x, y, z) come:
B b = new B(someFn(x, y, z))
Inoltre, se qualcuno non sarebbe stato statico, avresti potuto scrivere una sottoclasse per la classe che la definisce e sovrascriva un po 'di modifica del tipo di ritorno come (questa funzione è chiamata Tipo di ritorno covariante):
B someFn(x, y, z){
...
}