Я не знаю, упустил ли я что-то здесь, но у меня возникли проблемы с приведением объекта к его фактическому инициализированному типу. По сути, если я создаю объект с «SuperClass sc = new SubClass()», то я вызываю метод в sc, я хочу, чтобы метод мог вызывать метод (подкласс) вместо метода (суперкласс). Пример показан ниже:
public class Example
{
public static void act(SuperClass a) {
System.out.println("SuperClass");
}
public static void act(SubClass a) {
System.out.println("SubClass");
}
public static void main(String[] args) {
SuperClass sc = new SubClass();
// want to find a way to call act(SubClass) instead of act(SuperClass)
act(sc);
}
}
class SuperClass {}
class SubClass extends SuperClass {}
Я использую шаблон посетителя прямо сейчас, но мне интересно, есть ли другие способы сделать это, возможно, через Java Reflection API?
Заранее большое спасибо!
== редактировать ==
Я знаю, что, как правило, с объектно-ориентированным подходом лучше привязать функциональность к самим суперклассам/подклассам, но для моих конкретных случаев использования у меня есть куча подклассов, которые являются неизменяемыми классами моделей, которые должны быть переданы различным типам механизмов выполнения (подумайте разные классы «Пример»). Классы подклассов/моделей должны содержать только неизменяемую информацию, не более того, а фактическая реальная функциональность связана с механизмом выполнения (класс примера). Вот почему я задаюсь вопросом об альтернативах шаблону посетителя. У кого-нибудь есть способ восстановить фактическую «инициализированную» информацию в Java? Если да, то большое спасибо.
И из-за характера проблемы я не могу использовать прямое приведение типов... Представьте, что у меня есть массив суперклассов, где каждый элемент может быть подклассом1, подклассом2, подклассом3, и все они простираются от суперкласса.
Теперь, когда вы вытаскиваете элементы из Arraylist, вы получаете объект SuperClass, даже если на самом деле это могут быть SubClass1, SubClass2, SubClass3 и т. д.
Затем я хочу вызвать act(SubClass1) и иметь возможность вызывать правильный метод act() для текущего типа. Итак, я хочу в конечном итоге вызвать действие (SubClass1), действие (SubClass2), действие (SubClass3) вместо действия (SuperClass).
== изменить еще раз ==
Я придумал способ сделать это с помощью Java Reflection API, найдя фактический базовый тип подкласса с помощью Class.forName(имя класса), а затем динамически вызывая метод с правильной подписью метода. Я написал это в форме ответа где-то на этой странице для тех, кто интересуется этой проблемой. Обратите внимание, что это не очень эффективный способ выполнить то, что я пытаюсь сделать здесь, и вам, вероятно, лучше использовать шаблон посетителя или операторы if-else, если вы застряли в моей ситуации.
Таким образом, ответ, который дал Никола Мусатти, наиболее близок к ответу на мой вопрос, хотя, как он также указал, по мере роста числа подклассов список операторов if-else становится очень длинным. Я выберу его ответ в качестве принятого ответа, поскольку в своем вопросе я четко не указал, что надеялся избежать проверок if-else.
В любом случае, сегодня я немного поиграл с Java Reflection API и придумал следующее:
SuperClass sc = new SubClass();
// Get the actual class of sc. actualClass now is SubClass.
Class actualClass = Class.forName(sc.getClass().getCanonicalName());
// Basically invoking act(SubClass sc) instead of act(SuperClass sc)
Class parameters[] = {actualClass};
Method method = Example.class.getMethod("act", parameters);
Object arguments[] = {sc};
method.invoke(null, arguments);
Это, безусловно, не лучший способ сделать что-то, особенно из-за потери производительности, налагаемой Java Reflection API. Это может быть лучше, чем шаблон посетителя или проверка if-else, если у вас есть миллион подклассов, поскольку, вероятно, для управления требуется меньше кода, однако пока я буду придерживаться шаблона посетителя, поскольку у меня нет миллиона подклассов для управления .
В любом случае, я просто подумал, что опубликую это здесь, чтобы показать, что это можно сделать, просто для тех, кому любопытно.