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

teraz rozszerzony klasy bazowej, takich jak:java, zainicjować podklasy z nadklasy

public class subClass extends Base{ 
    private boolean selected; 

    ... 
    getter und setter 
    ... 
} 

staję się lista obiektów bazy List<Base>

ale potrzebuję tej samej listy, ale jak List<SubClass> jest istnieje sposób na zainicjowanie podklasy z klasy bazowej?

przykład:

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

próbuję uniknąć ręcznego init każdego atrybutu Bazie Class do podklasy

zaktualizować moje pytanie jako wymagane w Komentarze: Design powyżej to tylko przykład. moja QUESTIN DOKŁADNIE JEST:

dlaczego przekształcenie BaseClass w SubClass (se Subclass extends BaseClass) nie jest możliwe? dlaczego Java dosn't pozwoli mi wykonać następujące czynności:

przykład:

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

następnie

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

po tym Object sub powinien mieć nazwę atrybutu z obiektu b a Atrybut jest zerowy

Dlaczego tak nie jest w przypadku java?

Przepraszam za mój zły język angielski, dzięki

+2

Inicjowanie podklasy z nadklasy - dlaczego? Brzmi to źle, w najlepszym wypadku, aw najgorszym - niebezpieczne. –

+0

Gdzie jest zdefiniowane pole 'Lista '? W samej klasie 'Base'? Czy masz kontrolę nad tym, gdzie została zadeklarowana i jak została zainicjowana? – Perception

+1

Wysoce sugeruję, aby zagłębić się w "preferowanie kompozycji przez dziedziczenie" - google to. Znajdziesz tu interesujące dyskusje na ten temat. Mówię to tylko dlatego, że wygląda na to, że próbujesz rozpaczliwie nadużyć tego przywileju. –

Odpowiedz

7

Jeśli masz List<Base>, to nie można przekonwertować go do List<SubClass>. Dzieje się tak głównie dlatego, że lista nie może zawierać instancji SubClass. Najlepiej można to zrobić:

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

Generalnie jednak, gdy znajdziesz się robić tego typu rzeczy, jest coś nie tak z projektu. Możesz uniknąć podklasy Base i używając composition instead.

EDIT W oparciu o komentarze, to brzmi jak chcesz zbudować listę SubClass przypadkach na podstawie listy zawierającej Base przypadkach, jak na początek. Jednym z podejść jest zdefiniowanie konstruktora dla SubClass, który przyjmuje argument jako Base.

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 
    ... 
} 

Następnie można skonstruować nową listę z:

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

dzięki za odpowiedź. Lista ma tylko Typy obiektów Bazy, więc nie są to instancje Podklasy na liście. ale dlaczego rzucanie klasy jest złe? atrybuty w SubClass może być null po rzutowaniu, mogę ustawić go ręcznie jak w moim przykładzie powyżej. co o tym myślisz? –

+0

znaczy, że po zakończeniu rzutowania SubClass powinien mieć wszystkie atrybuty klasy bazowej, a pozostałe atrybuty w SubClass będą miały wartość zerową –

+0

@ Rami.Q - Dobra, twoje komentarze wyjaśniły mi coś o tym, czego chcesz. Poprawiłem swoją odpowiedź, by odpowiedzieć na to pytanie. –

2

Wygląda mieć klasę z wieloma atrybutami i bez łatwy sposób je wszystkie ustawienia. Natrafiłeś teraz na problem, w którym potrzebujesz klasy z dodatkowym atrybutem, ale musisz poradzić sobie z tym bałaganem w klasie bazowej.

I sugerują, że zamiast tworzenia podklasy i odlewania, utworzyć klasy otoki wokół brzydkiego One:

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 
} 

Teraz, kiedy trzeba stworzyć tę nową listę można zawinąć wszystko w starej listy

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); 
} 

Idealnie BigDumbClass by realizować interfejs Wrapper może również wprowadzania, umożliwiając owijka na przesunięcie wszystkich połączeń na przykład to zawinięte.

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(); 
    } 
} 

W przeciwnym razie można dostarczyć pobierającego do instancji i uzyskać do niego bezpośredni dostęp.

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

Tylko dlatego, że masz referencję do super klasy, nie oznacza to, że wskazujesz na super klasę. "Base baseRef" może wskazywać na SubClass1, więc "SubClass2 subRef = (SubClass2) baseRef" nie jest prawidłowym rzutem. –

2

Istnieje sposób: różne manipulacje oparte na specyfikacjach Java Beans.

Na przykład:

Commons BeanUtils

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

to działa na podstawie get/ustawiaczy o tej samej nazwie. Nie kopiuje pól wewnętrznych.

Jeśli potrzebne jest skopiowanie wewnętrznych pól, w rzeczywistości nie jest to trudne do wdrożenia przy użyciu javax.lang.reflect.

Powiązane problemy