Апкаст при создании объекта - PullRequest
5 голосов
/ 29 марта 2011

Допустим, у вас есть Shape базовый класс и различные производные типы: Circle и т. Д.

Есть ли какая-либо причина для того, чтобы подниматься вверх прямо при создании нового объекта, написав это:

Shape s = new Circle();

вместо этого:

Circle s = new Circle();

и s объекты, сделанные каждым из этих двух утверждений, чем-либо отличаются друг от друга?

Ответы [ 7 ]

3 голосов
/ 29 марта 2011

Вы можете утверждать, что ваш первый пример (т. Е. Shape s = new Circle();) может иметь те же преимущества, что и "кодирование интерфейса", даже если Shape может быть абстрактным или даже конкретным базовым классом. Так, например, если вы когда-либо используете только методы, определенные в Shape, а не методы, специфичные для Circle, то вы можете довольно легко просто изменить используемую реализацию на Square, например, просто изменив одну строку кода, то есть Shape s = new Square(); .

Объекты одинаковы в обоих ваших примерах, причина, по которой первый вариант можно рассматривать лучше, это скорее стиль. Кодирование интерфейсов может сделать кодовую базу более легко расширяемой и модифицируемой.

3 голосов
/ 29 марта 2011

Эти два оператора создадут один и тот же объект в отношении JVM.Нередко можно показать, что вы планируете использовать объект только для базового класса или интерфейса.Например, это часто встречается:

List<String> list = new ArrayList<String>();

Хотя обычно это не очень хорошая идея, вы можете привести Shape обратно в Circle, если точно знаете, что он один, например, с Shape s выможет вернуть его к Circle c с помощью:

if (s instanceof Circle) {
    Circle c = (Circle) s;
    // handle Circle case
}
1 голос
/ 29 марта 2011

В ответ на ваш вопрос, два объекта абсолютно одинаковы. Обе ссылки могут указывать на один и тот же объект:

Circle c = new Circle();
Shape s = c;

Кодирование интерфейсов позволяет вам изменять класс реализации с минимальным воздействием на ваш код. Скажем, у вас есть это:

Set<String> names = new HashSet<String>();         // using Set reference not HashSet
names.add("Frank");
names.add("John");
names.add("Larry");

for(String name: names) {
    System.out.println(name + " is in the team");
}

Теперь ваши требования меняются, и вы хотите, чтобы имена печатались в алфавитном порядке, т. Е. Используйте HashSet вместо TreeSet. Поскольку вы закодировали интерфейс и не использовали никаких методов, специфичных для класса HashSet, вам нужно изменить только одну строку:

Set<String> names = new TreeSet<String>();   // the only line of code that changes
names.add("Frank");
names.add("John");
names.add("Larry");

for(String name: names) {
    System.out.println(name + " is in the team");
}

Интерфейсы также позволяют использовать внедрение зависимостей. Он позволяет вам использовать классы, которые могут даже не существовать на момент написания кода.

http://en.wikipedia.org/wiki/Dependency_injection

1 голос
/ 29 марта 2011

Объект создан точно так же.

Последствия апкастинга:

  1. обобщение при хранении: все объекты различного специализированного типа могут быть связаны как один и тот же интерфейс и могут быть сохранены вместе в структуре данных.(Как указано @ WhiteFang34: List )
  2. обобщение при доступе к методу объектов: клиентский класс может вызывать метод Shape, не зная реального типа (обычно вы можете использовать фабрику для создания объекта, который возвращаетобщий интерфейс Shape, поэтому клиентский класс не знает о реальном типе объектов, но доступны только методы интерфейса Shape)
0 голосов
/ 29 марта 2011

Я согласен с тем, что говорит @ WhiteFang34.

См. Это Кодирование интерфейсов? Это может помочь вам.

0 голосов
/ 29 марта 2011

Circle s = new Circle ();
здесь объект ссылается на класс Cricle

Shape s = new Circle ();здесь объект ссылается на интерфейс

Оба одинаковы.

0 голосов
/ 29 марта 2011

Нет, сами объекты не отличаются.Отличается только то, что, по мнению компилятора, он видит (например, какие методы доступны).

Одна из причин, чтобы сделать приведение подобным образом, это выразить, как вам нравится обрабатывать объект (чтобы вы могли легко вставить другойвместо производного класса).

...