Назначить родительский класс переменной дочернего класса в Java

У меня есть родительский класс и несколько дочерних классов (назовем их parent и child1, child2, child3 и т. д.).

У меня есть функция, которая принимает двумерный массив parents и сглаживает его до одномерного массива следующим образом:

public parent[] flatten(parent[][] input);

В контексте вызова я знаю, что когда я передаю массив, все элементы имеют один и тот же тип, и этот тип является одним из дочерних типов (в частности, я знаю, КАКОЙ это дочерний тип). Я хочу иметь возможность взять определенный элемент массива и присвоить его переменной соответствующего дочернего типа, например:

child1 c = flatten(input)[0];

Я знаю об утверждениях типа (соответствующее сообщение SO: Утверждение объекта определенного типа), но я не могу найти способ действительно присвоить переменную с правильным типом, если утверждение успешно. Возможно ли такое в Java? Я знаю, что это возможно и в других языках, например в Go.


person joshlf    schedule 24.06.2013    source источник


Ответы (4)


Вы не можете выделить универсальные массивы, но если вы хотите передать out-param, вы можете использовать дженерики для позаботимся о кастинге для вас:

 public <T extends Parent> boolean addAll(T[][] input, 
                                          T[] output) {
   //set up you indices
   output[x] = input[z];
   return true;
}

Если вы передадите непревзойденный ввод/вывод, вы получите ошибку времени выполнения, в противном случае это должно просто работать.

person Paul Rubel    schedule 24.06.2013

Вы действительно хотите назначить его какому-то дочернему типу. Вы можете работать со ссылкой на класс Parent для доступа к методам класса Child, если метод также определен в классе Parent.

В противном случае вы можете ввести приведение к соответствующему типу:

child1 c = (child1)flatten(input)[0];

Но вы должны быть уверены, что тип только child1. Обычно приведение типов не является хорошей идеей. Это признак плохого кода (но не всегда). Вы должны стараться избегать этого, насколько это возможно.

person Rohit Jain    schedule 24.06.2013
comment
Вы знаете, что произойдет, если я приведу тип и ошибусь? В данном случае этого не произойдет; Мне просто интересно. - person joshlf; 24.06.2013
comment
Он выдаст ClassCastException во время выполнения. Если вы уверены, что здесь этого не произойдет, то ничего страшного. Но это всего лишь общая идея, чтобы избежать такого рода приведения. - person Rohit Jain; 24.06.2013
comment
Ммм ок круто. Я ссылаюсь на Go, где правильность приведения типов должна быть подтверждена во время компиляции, а утверждения типов (отдельная языковая конструкция) используются для приведения, которые не могут быть подтверждены до времени выполнения. - person joshlf; 24.06.2013

Попробуйте "литье", например:

Child1 c = (Parent)flatten(input)[0];
person morgano    schedule 24.06.2013

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

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof

Вкратце: проверьте экземпляр класса, к которому вы выполняете приведение.

if (flatten(input)[0] instanceof child1)
       Child1 c = (Parent)flatten(input)[0];
person Eric    schedule 24.06.2013