2013-04-04 8 views
10
public class Base { 
    //long list of attributes 
    // no Constructor using fields 
    // no init methode 
    // i cannot change this class 
} 

jetzt erweitert i die Basisklasse wie:java, initialisieren SubClass von Oberklasse

public class subClass extends Base{ 
    private boolean selected; 

    ... 
    getter und setter 
    ... 
} 

i werden eine Liste von Basisobjekt List<Base>

, aber ich brauche die gleiche Liste, sondern als List<SubClass> ist Gibt es eine Möglichkeit, die Unterklasse von der Basisklasse zu initialisieren?

Beispiel:

for(Base b: list){ 
    SubClass sub = (SubClass)b; // Thats wrong i know 
    if(...){ 
     sub.setSelected(true); 
    } 
    newList.add(sub); 
} 

ich versuche, das Handbuch init jedes Attribut des Basis Class zum SubClass

ich meine Frage zu aktualisieren, um zu vermeiden, wie in den Anmerkungen angefordert: der Entwurf oben ist nur ein Beispiel. Mein QUESTIN GENAU IST:

Warum ist die Konvertierung von BaseClass in SubClass (sence Subclass extends BaseClass) nicht möglich? warum Java dosn't erlauben Sie mir folgendes zu tun:

Beispiel:

Class Base{ 
    private String name; 
..... 
} 
Class SubClass extends Base{ 
    private String title; 
} 

dann

Base b = DBController.getById(...); 
SubClass sub = (SubClass)b; 

nach, dass das Objekt sub sollte den Attributnamen aus dem Objekt b haben und die title Attribut ist null

Warum ist das in Java nicht der Fall?

sorry für mein schlechtes Englisch, dank

+2

Initialize Unterklasse von Superklasse - warum? Das hört sich im besten Fall schlecht und im schlimmsten Fall gefährlich an. –

+0

Wo ist das Feld "List " definiert? In der Base-Klasse selbst? Haben Sie die Kontrolle darüber, wo und wie es initialisiert wurde? – Perception

+1

Ich schlage vor, Sie schauen in "bevorzugen Zusammensetzung über die Vererbung" - google es. Sie werden einige interessante Diskussionen zu diesem Thema finden. Ich sage das nur, weil es so aussieht, als ob Sie verzweifelt versuchen, das Privileg zu missbrauchen. –

Antwort

7

Wenn Sie eine List<Base> haben, dann können Sie nicht wandeln es in einem List<SubClass>. Dies liegt hauptsächlich daran, dass die Liste keine Instanzen von SubClass enthalten kann. Das Beste, was Sie tun können, ist:

List<SubClass> newList = new List<SubClass>(); 
for(Base b: list){ 
    if (b instanceof SubClass) { 
     SubClass sub = (SubClass)b; 
     . . . 
     newList.add(sub); 
    } 
} 

Im Allgemeinen jedoch, wenn man sich selbst tun, diese Art der Sache zu finden, es ist etwas falsch mit Ihrem Design. Sie sollten die Unterklasse Base vermeiden und composition instead verwenden.

EDIT Basierend auf Ihre Kommentare, es klingt wie Sie eine Liste von SubClass Instanzen mit einer Liste von Base Instanzen als Start konstruieren wollen. Ein Ansatz besteht darin, einen Konstruktor für SubClass zu definieren, der ein Base als Argument verwendet.

public class SubClass extends Base{ 
    private boolean selected; 

    public SubClass() { 
     // default constructor 
    } 

    public SubClass(Base original) { 
     // copy constructor -- initialize some fields from 
     // values in original, others with default values 
    } 
    ... 
    getter und setter 
    ... 
} 

Dann können Sie Ihre neue Liste konstruieren mit:

List<SubClass> newList = new List<SubClass>(); 
for(Base b: list){ 
    SubClass sub = new SubClass(b); 
    . . . 
    newList.add(sub); 
} 
+0

danke für die Antwort. Die Liste hat nur den Basistyp Objects, das sind also keine Subclass-Instanzen in der Liste. Aber wieso ist die Klasse falsch? Attribute in der SubClass können nach dem Casting null sein, das kann ich manuell einstellen wie in meinem obigen Beispiel. Was denkst du darüber? –

+0

ich meine, nach dem Gießen SubClass sollte alle Attribute der Basisklasse und der Rest Attribute in SubClass wäre null –

+0

@ Rami.Q - Okay, Ihre Kommentare geklärt zu mir etwas über das, was Sie wollen. Ich habe meine Antwort überarbeitet, um dies zu beheben. –

2

Sie scheinen eine Klasse mit einer Menge von Attributen zu haben und keine einfache Möglichkeit, sie alle zu setzen. Sie sind jetzt in ein Problem hineingerannt, wo Sie eine Klasse mit einem zusätzlichen Attribut benötigen, aber Sie müssen sich mit dem Durcheinander einer Basisklasse befassen.

Ich schlage vor, dass anstelle einer Unterklasse und Gießen von Erstellen Sie eine Wrapper-Klasse um die hässliche erstellen:

public class BigDumbClass { 
    // A lot of attributes 
    // No Constructor 
    // No init method 
} 

public class Wrapper { 
    private BigDumbClass base; 
    private boolean selected; 

    public Wrapper(BigDumbClass base) { 
     this.base = base; 
     this.selected = false; 
    } 

    //getters and setters 
} 

Nun, wenn Sie diese neue Liste erstellen müssen Sie alles, was in der alten Liste wickeln können

List<BigDumbClass> oldList = someData(); 
List<Wrapper> wraps = aNewList(); 
for (BigDumbClass bigDumb : oldList) { 
    Wrapper wrap = new Wrapper(bigDumb); 
    if (someCondition()) { 
     wrap.setSelected(true); 
    } 
    wraps.add(wrap); 
} 

Idealerweise weise~~POS=HEADCOMP würde BigDumbClass eine Schnittstelle implementieren, die Wrapper könnte auch implementieren, so dass der Wrapper alle Anrufe auf die Instanz verschieben es gewickelt hat.

public class BigDumbClass implements SharedInterface { 
    // All the stuff outlined above 
} 

public class Wrapper implements SharedInterface { 
    // All the stuff outlined above 

    // Methods defined in SharedInterface 
    public void doSomething() { 
     base.doSomething(); 
    } 
} 

Andernfalls können Sie einen Getter für die Instanz bereitstellen und direkt darauf zugreifen.

BigDumbClass base = wrapper.getBase(); 
base.doSomething(); 
+0

Nur weil Sie eine Referenz für eine Superklasse haben, bedeutet das nicht, dass Sie auf eine Superklasse verweisen. 'Base baseRef' verweist möglicherweise auf eine SubClass1, daher ist 'SubClass2 subRef = (SubClass2) baseRef' keine gültige Umwandlung. –

2

Es gibt einen Weg: Verschiedene Java-Bohnen-basierte Manipulation.

Zum Beispiel:

Commons BeanUtils

for(Base base: list){ 
    SubClass sub = new SubClass(); 
    PropertyUtilsBean.copyProperties(sub, base); 
    if(...){ 
     sub.setSelected(true); 
    } 
    newList.add(sub); 
} 

Diese arbeitet nach bekommen/Setter mit dem gleichen Namen. Kopiert interne Felder nicht.

Wenn Sie interne Felder kopieren mussten, ist es mit javax.lang.reflect nicht so schwer zu implementieren.