2015-11-19 3 views
2

Когда я перехожу через мой онлайн-учебник, я наткнулся на этот урок. У меня есть интерфейс и два класса, которые реализуют этот интерфейс.В полиморфизме Java, могут ли быть созданы все классы, реализующие интерфейс, как интерфейс этого типа?

public interface Payable { 
double getPaymentAmount(); 
} 

и

  • класс Invoice, который реализует интерфейс выше Payable
  • класса SalariedEmployee, который расширяет абстрактный класс Employee, который реализует интерфейс Payable.
  • Испытательный класс, который содержит основной метод проверки этого.

В настоящее время в тестовом классе, при создании массива объектов, тип объекта был передан как Payable[], а не SalariedEmployee[] или Invoice[], как

public static void main(String[] args) { 
    Payable[] payableObjects = new Payable[4]; 
    payableObjects[0] = new Invoice("0000", "abc", 1,2); 
    payableObjects[1] = new SalariedEmployee("test", "user", "000-000", 35); 
  • Является ли это потому, что все классы реализует интерфейс Payable []?
  • Если интерфейс определен в иерархии верхнего уровня, всегда ли возможно создавать объекты всех классов, реализующих этот интерфейс?
+3

1. Да, вы получили бы ошибку компилятора, если бы это было не так. 2. Да, возьмите пример «Список» или «Карта», где вы всегда должны объявлять переменную как «Список» или «Карта», чтобы иметь возможность изменять тип объекта assgning. Ваша общая информация о том, что вы только хотите вызвать методы, предоставляемые этим конкретным интерфейсом. – SomeJavaGuy

+0

Спасибо @KevinEsche. Пожалуйста, опубликуйте его как ответ, и я соглашусь с ним. – scott

+0

Да, в этом весь смысл полиморфизма. –

ответ

1

для вашего первого вопроса: да, вы получили бы ошибку компилятора, если бы это было не так.

для второго случая, возьмите в качестве примера List или Map.Посмотрите на следующий пример. Мы объявляем список, но в зависимости от флага, мы хотим, чтобы этот конкретный List действовать разные, так как она представляет собой другой класс

public class BookList{ 
    List <String> list; 

    public BookList(boolean flag) { 
     if(flag) { 
      list = new ArrayList<>(); 
     } else { 
      list = new LinkedList<>(); 
     } 
    } 
} 

Поскольку мы объявили его как List мы можем назначать различные типы списков которые реализуют это interface. Вы можете легко изменить usecase этого класса, в то время как вы все еще можете использовать каждый метод, предоставляемый интерфейсом.

Это то, что делает ваш массив Payable. Вы хотите назначить в этот массив разные типы классов, которые все реализуют этот интерфейс.

Это упростит создание методов для этого конкретного интерфейса. Возьмем метод суммирования в качестве примера для вашего случая.

public int sumPayable(Payable[] payables) { 
    int sum = 0; 
    for(Payable p : payables) { 
     sum += p.getPaymentAmount(); 
    } 
    return sum; 
} 

В этом случае wouldn't важно, что actuall класс каждого из этих классов, которые делают реализует Payable это, так как вы могли бы просто передать массив, как ты создать, к этому методу.

+0

Спасибо @ Кевин. Я еще не сталкивался с этим оператором ''. Для чего он используется и как он называется? Если вы можете дать мне термин для поиска, я бы это сделал. – scott

+1

@scott это [Generics] (https://docs.oracle.com/javase/tutorial/java/generics/why.html) – SomeJavaGuy

4

Ваше название вопроса не является грамматическим, но выбор слова предполагает, что происходит тонкое непонимание понятий.

Вы можете создать класс только в этом классе. То есть вы не можете написать new Payable и как-то ожидать, что будут какие-либо Invoice или SalariedEmployee объектов, создаваемых.

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

Что происходит в примере, так это то, что создается массив из четырех ссылок Payable. Эти ссылки еще не указывают ни на что (они равны нулю), и пока нет объектов Invoice или SalariedEmployee объектов, только объектов массива.

Затем код создает два объекта и присваивает их двум ссылкам. Это работает так же, как если бы элементы массива были независимыми переменными. (Почти, но разница обусловлена ​​ковариацией массива, что не важно на данном этапе.) В частности, результат оператора new имеет тип Invoice в первом случае, а не Payable. Вы можете назначить Invoice ссылке Payable, но преобразование происходит при назначении, а не при создании.

Так что технически ответ на ваш вопрос в заголовке «нет», объекты всегда создаются как тип, указанный вами в выражении new, но впоследствии вы можете преобразовать ссылки ».