Как уменьшить Java-объект? - PullRequest
19 голосов
/ 27 октября 2010

Я пытаюсь понять полиморфизм Java, и у меня есть один вопрос о снижении рейтинга объекта.Допустим, для этого примера у меня есть два подкласса 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

Ответы [ 4 ]

9 голосов
/ 27 октября 2010

Если вы хотите создать экземпляр типа, который может различаться в зависимости от нелокальных условий, используйте Абстрактная фабрика (как описано в книге «Шаблоны проектирования»).

В простейшем виде:

interface AnimalFactory {
    Animal createAnimal();
}

class DogFactory implements AnimalFactory {
    public Dog createAnimal() {
        return new Dog();
    }
}

Обратите внимание, что есть разница между статическим типом ссылки и динамическим типом объекта. Даже если у вас есть ссылка Animal, если исходный объект - Dog, он все равно ведет себя как Dog.

3 голосов
/ 27 октября 2010

Вы должны приводить только к классу, которым на самом деле является объект, поэтому, если у вас есть Dog, который расширяет Animal, вы можете привести его к Animal (потому что он один), но вы не должны кастоватьот Animal до Dog, потому что не все Animal с Dog с.Класс Dog вполне может иметь дополнительные поля, которые не реализуются классом Animal, поэтому приведение не имеет смысла (для чего вы инициализируете эти значения?).

1 голос
/ 27 октября 2010

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.

0 голосов
/ 04 ноября 2010

Здесь вы говорите о даункастинге, поэтому в этом сценарии всегда следует использовать суперкласс в качестве ссылки, а дочерний объект должен указывать на это.Это usd в основном в заводской скороговорке.

...