Примечание: код с последовательностями "if (x instanceof MyClass)
обычно указывает на то, что вы недостаточно используете полиморфизм. Код обычно может быть реорганизован, чтобы избавиться от необходимости проверять это. Но я проигнорирую это ради ответа на вопрос заданный вопрос.
Вы можете делать то, что пытаетесь сделать, но не без некоторых изменений кода. Перегрузка методов не может делать то, что вам нужно, потому что в Java перегрузка методов решается во время компиляции. Таким образом, если у вас есть два метода в классе, где оба метода имеют одно и то же имя, один и тот же тип возвращаемого значения, но разные типы параметров, то любой код, вызывающий этот перегруженный метод, должен явно указать, какой из них будет вызван. Ваш текущий код делает это с типами, которые он предоставляет из-за использования явных приведений, но полностью динамическая версия не делает. Если перегрузка метода будет решена во время выполнения, тогда ваш код будет делать то, что вы хотите. Но поскольку это решено во время компиляции, ваш код не компилируется.
Чтобы решить вашу проблему, вы можете использовать дженерики или реструктурировать свой код. Сначала я представлю тестовый набор, который показывает очень упрощенную версию того, с чего вы начинаете:
public class Test {
public void test(Object obj) {
if (obj instanceof Horse) {
Horse c = (Horse) obj;
noise(c);
}
if (obj instanceof Cow) {
Cow c = (Cow) obj;
noise(c);
}
}
public void noise(Horse h) {
System.out.println("Neigh");
}
public void noise(Cow c) {
System.out.println("Moo");
}
public static void main(String[] args) {
Object o1 = new Horse();
Object o2 = new Cow();
Test tester = new Test();
tester.test(o1);
tester.test(o2);
}
}
class Horse {}
class Cow {}
Этот код запускается и делает то, что вы ожидаете. Он печатает «Neigh», а затем «Moo».
Вы пытаетесь заменить
if (obj instanceof Horse) {
Horse c = (Horse) obj;
noise(c);
}
с
if (obj instanceof Horse) {
handleNoise(obj, Horse.class);
}
и добавление метода для его обработки (упрощенно):
void handleNoise(Object obj, Class clazz) {
noise(clazz.cast(obj));
}
и, как я уже говорил, это не работает, перегрузка noise
определяется во время компиляции. Компилятор видит, что вы используете приведение, но не знает во время компиляции, что это за тип. Таким образом, он не может выбрать перегрузку, и компиляция не удалась.
Лучший способ решить эту проблему - использовать полиморфизм, потому что полиморфизм определяется во время выполнения. То есть, чтобы все эти классы реализовали некоторый интерфейс, а затем переместили соответствующий код в отдельные классы. Вот пример, который делает это:
public class Test {
public void test(Animal obj) {
obj.noise();
}
public static void main(String[] args) {
Animal o1 = new Horse();
Animal o2 = new Cow();
Test tester = new Test();
tester.test(o1);
tester.test(o2);
}
}
interface Animal {
void noise();
}
class Horse implements Animal {
public void noise() {
System.out.println("Neigh");
}
}
class Cow implements Animal {
public void noise() {
System.out.println("Moo");
}
}
Обратите внимание, насколько проще метод теста! Если вы можете заставить каждый элемент реализовывать интерфейс, который обрабатывает то, что вы называете stringProp ниже, то вы можете упростить часть пути:
if (obj instanceof Cust) {
loopOverSet(c.getCustPhonSet());
} else if (obj instanceof Name) {
loopOverSet(c.getCustNameSet());
}
// and so on for the rest...
и затем добавьте метод:
void loopOVerSet(Set cxSet) {
if (cxSet != null && cxSet.size() > 0) {
Iterator cxSetIterator = cxSet.iterator();
while (cxSetIterator.hasNext())
{
((StringProp)cxSetIterator.next()).stringProp();
}
}
}
Это предполагает, что ранее перегруженные методы stringProp
были перемещены в отдельные классы CustPhone
и CustName
и т. Д., И что все эти классы реализуют некоторый интерфейс, который я назвал StringProp
, где этот интерфейс определяет метод stringProp()
. Поскольку этот код использует переопределение вместо перегрузку , решение будет принято во время выполнения.