Как скрыть объект Java?
Я пытаюсь понять полиморфизм Java, и у меня есть один вопрос о downcasting объекте.
Скажем, для этого примера у меня есть два подкласса Dog и Cat, которые наследуются от суперкласса Animal
Из того, что я понял, единственный способ опускать объект - это если этот объект уже имеет хороший тип, например:
Animal a = new Dog();
Dog d = (Dog) a;
Это работает правильно?
Но что, если я хочу создать обычного животного, не зная, что это будет, а затем бросить его, когда я знаю, как я могу это сделать?
Animal a = new Animal();
Dog d = (Dog) a;
Это приведет к исключению ClassCastException во время выполнения?
Единственный способ, которым я нашел это, - создать новый конструктор Dog, который создает собаку из обычного животного:
Animal a = new Animal();
Dog d = new Dog(a);
с
public Class Dog extends Animal{
public Dog(Animal a){
super(a);
}
}
Итак, мой вопрос: как я должен это делать?
- Я делаю это наилучшим образом?
- Я не должен делать это вообще, если это нужно, значит, моя программа плохо задумана?
- Есть ли лучший способ, который я пропустил?
Спасибо большое!
nbarraille
Ответы
Ответ 1
Если вы хотите создать экземпляр типа, который может меняться в зависимости от нелокальных условий, используйте Аннотация Factory (as описанных в книге "Шаблоны проектирования" ).
В нем простейшая форма:
interface AnimalFactory {
Animal createAnimal();
}
class DogFactory implements AnimalFactory {
public Dog createAnimal() {
return new Dog();
}
}
Обратите внимание, что также существует разница между статическим типом ссылки и динамическим типом объекта. Даже если у вас есть ссылка Animal
, если исходный объект является Dog
, он все еще ведет себя как a Dog
.
Ответ 2
Вы должны использовать только класс, который действительно является объектом, поэтому, если у вас есть Dog
, который расширяет Animal
, вы можете применить его к Animal
(потому что он один), но вы не должны бросать a Animal
до a Dog
, потому что не все Animal
являются Dog
s. Класс Dog
может иметь дополнительные поля, которые не реализуются классом Animal
, и поэтому приведение не имеет смысла (что вы инициализируете эти значения?).
Ответ 3
Java - это строго типизированный язык, и это означает, что вы можете только передать объект к типу, из которого он распространяется (либо суперкласс, либо интерфейс).
Даже если вы "подделываете это", например. скопируйте все методы и поля классов, вы просто не можете подвергнуть объект типу, который он не расширяет.
public class Foo{
public String phleem;
public void bar(){
}
}
public class Bar{
public String phleem;
}
public interface Baz{
public void bar();
}
Учитывая приведенный выше код, вы не можете использовать объект Foo
для Bar
или Baz
, хотя структура класса, по-видимому, подразумевает, что вы могли бы. Наследования нет, поэтому вызывается ClassCastException
.
Ответ 4
Здесь вы говорите о downcasting, поэтому в этом сценарии всегда суперкласс должен использоваться как ссылка, а дочерний объект должен указывать на это.
Это usd в основном в factory patter.