#java #inheritance
#java #наследование
Вопрос:
У меня простая иерархия, Base
и Derived
у меня есть их обычные значения.
class Base{}
class Derived1 extends Base{}
class Derived2 extends Base{}
class Test {
void method1() {
Base b1 = new Derived1();
Base b2 = new Derived2();
call(b1);
call(b2);
}
void call(Derived1 d){}
void call(Derived2 d){}
}
Почему java не позволяет мне вызывать call
метод с разными типами?
В нем говорится: The method call(Derived1) in the type Test is not applicable for the arguments (Base)
Разве он не может определить тип во время выполнения и вызвать соответствующий метод?
Ответ №1:
Разрешение метода в java является статическим. Другими словами, время компиляции.
Это имеет множество преимуществ. Например, этот код правильно определен как неуправляемый и не будет компилироваться:
Base b3 = new Derived3();
call(b3); // does not compile in java.
// which is correct, as there is no call(Derived3) method at all.
Что еще более важно, каждый вызов метода в коде Java известен во время записи (время компиляции). Это означает, например, что вы можете щелкнуть CMD / CTRL по методу в вашем редакторе и перейти прямо к методу, который он вызывает. И это не предположение, что вы получаете с более динамичными языками, такими как python или javascript. Это неопровержимый факт, потому что это буквально то, что заканчивается в файле класса.
Java ИМЕЕТ динамическую отправку: «Идентификатор» метода (это комбинация имени, типов параметров, возвращаемого типа и класса, в котором он находится) разрешается во время записи (компиляции) и записывается в файл класса, но какая фактическая реализация этогов конечном итоге выбирается метод, эта часть является динамической:
class Base {
void foo() {
System.out.println("base");
}
}
class Child extends Base {
void foo() {
System.out.println("child");
}
}
Base b = new Child();
b.foo(); // prints "child"
«Идентификатор» foo()
ищется в базовом классе, и поэтому этот код компилируется: Base имеет метод foo() . Но фактическая реализация, вызываемая во время выполнения, является динамической и, поскольку b
ссылается на объект типа Child, в конечном итоге является его дочерней реализацией.
Комментарии:
1. ОК. Учитывая, что эта штука не работает, теперь мне нужно переделать то, что я пытался реорганизовать, используя шаблон проектирования: (
2.
call
Предположительно, переместить метод в базовый. Это или новый интерфейс, которыйDerived1
иDerived2
оба реализуют. Трудно сказать без более подробной информации.