Java, инициализировать SubClass от SuperClass
public class Base {
//long list of attributes
// no Constructor using fields
// no init methode
// i cannot change this class
}
теперь я расширил базовый класс следующим образом:
public class subClass extends Base{
private boolean selected;
...
getter und setter
...
}
i ставьте список базового объекта List<Base>
но мне нужен тот же список, но как List<SubClass>
есть ли способ инициализировать подкласс из базового класса?
Пример:
for(Base b: list){
SubClass sub = (SubClass)b; // Thats wrong i know
if(...){
sub.setSelected(true);
}
newList.add(sub);
}
Я пытаюсь избежать ручной инициализации каждого атрибута базы Class
в SubClass
i обновляю свой вопрос по запросу в комментариях:
Дизайн, приведенный выше, является лишь примером. мой QUESTIN ТОЧНО:
Почему преобразование BaseClass в SubClass (sence Subclass extends BaseClass
) невозможно? почему Java не разрешает мне делать следующее:
Пример:
Class Base{
private String name;
.....
}
Class SubClass extends Base{
private String title;
}
затем
Base b = DBController.getById(...);
SubClass sub = (SubClass)b;
после этого объект sub
должен иметь имя атрибута из объекта b
и атрибут title
имеет значение null
почему это не так в java?
Извините за мой плохой английский,
спасибо
Ответы
Ответ 1
Если у вас есть List<Base>
, вы не можете преобразовать его в List<SubClass>
. Это происходит главным образом потому, что список не может содержать экземпляры SubClass
. Лучшее, что вы можете сделать, это:
List<SubClass> newList = new List<SubClass>();
for(Base b: list){
if (b instanceof SubClass) {
SubClass sub = (SubClass)b;
. . .
newList.add(sub);
}
}
Как правило, однако, когда вы обнаруживаете, что занимаетесь подобным делом, что-то не так с вашим дизайном. Возможно, вы захотите избежать подклассификации Base
и вместо .
РЕДАКТИРОВАТЬ. На основе ваших комментариев кажется, что вы хотите создать список экземпляров SubClass
, используя список экземпляров Base
в качестве запуска. Один из подходов заключается в определении конструктора для SubClass
, который принимает 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
...
}
Затем вы можете создать свой новый список:
List<SubClass> newList = new List<SubClass>();
for(Base b: list){
SubClass sub = new SubClass(b);
. . .
newList.add(sub);
}
Ответ 2
У вас есть класс с множеством атрибутов и простой способ установить их все. Вы столкнулись с проблемой, когда вам нужен класс с дополнительным атрибутом, но вам приходится иметь дело с этим беспорядком базового класса.
Я предлагаю, чтобы вместо создания подкласса и кастинга вы создавали класс оболочки вокруг уродливого:
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
}
Теперь, когда вам нужно создать этот новый список, вы можете обернуть все в старый список
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);
}
В идеале BigDumbClass реализует интерфейс, который Wrapper также может реализовать, позволяя оболочке отложить все вызовы к экземпляру, который он завернул.
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();
}
}
В противном случае вы можете предоставить получателю экземпляр и получить к нему доступ напрямую.
BigDumbClass base = wrapper.getBase();
base.doSomething();
Ответ 3
Существует один способ: различные манипуляции на основе Java Beans.
Например:
Commons BeanUtils
for( Base base: list ){
SubClass sub = new SubClass();
PropertyUtilsBean.copyProperties( sub, base );
if(...){
sub.setSelected(true);
}
newList.add(sub);
}
Это работает на основе get/seters с тем же именем. Не копирует внутренние поля.
Если вам нужно скопировать внутренние поля, на самом деле это не так сложно реализовать с помощью javax.lang.reflect
.