Ваши тесты показывают, что вам весело с полиморфизмом. Итак, как вы, возможно, знаете, в Java мы можем сказать, что ваш объект имеет два типа:
- Тип stati c: основанный на объявлении вашей переменной:
Icecream a = ...
. Объект a имеет тип компиляции (то есть stati c) Icecream
. - Динамический c класс: в зависимости от влияния этой переменной:
... a = new Faloodeh()
.
Когда пишет код, допустим, что вы используете только тип stati c. Это означает, что компилятор знает о классах / полях / методах, которые вы можете использовать, и позволяет вам их использовать. По этой причине вы можете написать код:
Icecream a = new Icecream();
a.displayName("test");
И не можете написать:
Icecream a = new Icecream();
a.unknownMethod("test");
Компилятор знает, что в вашем классе Icecream есть метод с именем displayName
, который принимает вар-арг. Он также знает, что существует класс Faloodeh
. Компилятор знает, что этот класс может иметь свои собственные методы и поля, а также иметь доступ к методам и полям своего родителя.
Faloodeh b = new Faloodeh();
b.displayName("test");
Таким образом, в основном, когда вы объявляете и реализуете метод в классе, его потомки могут переопределить поведение, повторно внедрив метод. Что вы и сделали с методом void describe(String s)
.
Но метод displayName
хитрый, потому что вы называете его одинаково, но на самом деле они не одинаковы, потому что они оба являются аргументами брать. Давайте попробуем быть компилятором. Я скомпилировал оба ваших класса, и вот что я создал:
Icecream => displayName | varargs
Icecream => describe | String
Fadooleh => displayName | String
Faloodeh => describe | String
Теперь, при запуске кода, давайте посмотрим, какие методы вы на самом деле будете вызывать со строками в вашем main:
Icecream a = new Faloodeh();
Faloodeh b = (Faloodeh)a;
a.displayName("test"); => Icecram => displayName | varargs
b.displayName("test"); => Fadooleh => displayName | String
a.describe("test"); => Faloodeh => describe | String
b.describe("test"); => Faloodeh => describe | String
Почему первая строка вызывает метод displayName(String...)
, а не displayName(String)
? Поскольку статически компилятор видел, что вы используете тип Icecream для вызова метода displayName
, и динамически существует только один метод displayName с переменными, этот метод никогда не был переопределен Faloodeh. Следовательно, вы вызываете напрямую метод Icecream displayName
.
Если вы раскомментируете метод displayName(String s)
в Icecream, тогда у вас есть Faloodeh, вступающий во владение, потому что динамически Faloodeh имеет свою собственную реализацию на displayName(String)
Вот почему его называют.
Надеюсь, это поможет. Больше информации о полиморфизме: https://www.tutorialspoint.com/java/java_polymorphism.htm
** Редактировать ** Это почти та же причина. У обоих ваших классов статически есть метод displayName(String)
, а у другого - displayName(String...)
.
. При использовании b.displayName("test")
он сначала будет соответствовать displayName(String)
, реализованному только в вашем Icecream
объекте. , Следовательно, поведение.
Это будет невозможно, например:
Icecream a = new Faloodeh()
a.displayName("test", "test");
Поскольку Icecream
ничего не знает о методе с именем displayName(String...)
.