Polymorphism: dynamic dispatch and toString() · Полиморфизм: динамическая диспетчеризация и toString()
Polymorphism: one type, many behaviours
- Polymorphism means "many forms": one superclass type, many subclass behaviours.
- You can hold a
Dogor aCatin anAnimalvariable, because each is-anAnimal. - When you call a method, the object's real type decides which version runs.
Полиморфизм: один тип, много поведений
- Полиморфизм означает «множество форм»: один тип суперкласса, множество поведений подклассов.
- Вы можете хранить
DogилиCatв переменной типаAnimal, потому что каждый являетсяAnimal. - Когда вы вызываете метод, реальный тип объекта решает, какая версия будет выполнена.
Dynamic dispatch
- The variable's type (
Animal) decides which methods you are allowed to call. - But at run time, the actual object (
Dog) decides which overridden version runs. - This run-time choice is called dynamic dispatch — it is the heart of polymorphism.
Динамическая диспетчеризация
- Тип переменной (
Animal) определяет, какие методы вам разрешено вызывать. - Но во время выполнения программы реальный объект (
Dog) решает, какая переопределённая версия метода будет запущена. - Этот выбор во время выполнения называется динамической диспетчеризацией — это сердце полиморфизма.
public class Main {
public static void main(String[] args) {
Animal[] zoo = { new Dog(), new Cat(), new Dog() };
for (Animal a : zoo) {
System.out.println(a.speak()); // Woof, then Meow, then Woof
}
}
}
class Animal {
public String speak() { return "some sound"; }
}
class Dog extends Animal {
public String speak() { return "Woof"; }
}
class Cat extends Animal {
public String speak() { return "Meow"; }
}
One loop handles every subclass
- The loop above never asks "is this a Dog or a Cat?" — it just calls
speak(). - Each object answers in its own way. That keeps the loop short and general.
- Add a brand-new subclass later and the same loop works on it, unchanged.
Один цикл обрабатывает все подклассы
- Вышеуказанный цикл никогда не спрашивает «это собака или кошка?» — он просто вызывает
speak(). - Каждый объект отвечает своим собственным способом. Это делает цикл коротким и универсальным.
- Добавьте новый подкласс позже, и тот же самый цикл будет работать с ним без изменений.
toString(): every object inherits it from Object
- Every class in Java secretly extends a class called
Object, which has atoString(). - Override
toString()to say how your object should look as text. - Java calls it automatically when you print an object or join it with
+.
toString(): каждый объект наследует его от Object
- Каждый класс в Java тайно расширяет класс
Object, который содержит методtoString(). - Переопределите
toString(), чтобы указать, как ваш объект должен выглядеть в текстовом представлении. - Java вызывает его автоматически, когда вы выводите объект на экран или соединяете его со строкой через
+.
public class Main {
public static void main(String[] args) {
Object x = new Fraction(3, 4);
System.out.println(x); // 3/4 -- toString() runs
System.out.println("ratio " + x); // ratio 3/4
}
}
class Fraction {
private int numerator;
private int denominator;
public Fraction(int numerator, int denominator) {
this.numerator = numerator;
this.denominator = denominator;
}
public String toString() {
return numerator + "/" + denominator;
}
}
Common mistakes
- The actual object's method runs at run time (dynamic dispatch), not the variable's type.
- Override
toString()for readable output.
Распространенные ошибки
- Метод реального объекта запускается во время выполнения (динамическая диспетчеризация), а не метод типа переменной.
- Переопределите
toString()для получения читаемого вывода.
Now you try
- Use a superclass array, add a new subclass, and override
toString(). - A hidden Harness checks that the right version runs for each object.
- Press Run to compile, then Check answer. Your code runs on the server, so even the first run is fast.
Теперь попробуйте сами
- Используйте массив superclass, добавьте новый subclass и переопределите
toString(). - Скрытый тестовый фреймворк проверяет, что для каждого объекта запускается правильная версия метода.
- Нажмите Run для компиляции, затем Check answer. Ваш код выполняется на сервере, поэтому даже первый запуск быстрый.
Animal, Dog, and Cat are written for you. Complete the static method Zoo.chorus(Animal[] animals) so it returns every animal's sound joined by single spaces. Example: a Dog, Cat, Dog array gives "Woof Meow Woof". An empty array gives "". Loop and call speak() — let polymorphism pick the right sound. · Классы Animal, Dog и Cat написаны за вас. Завершите статический метод Zoo.chorus(Animal[] animals) так, чтобы он возвращал звуки всех животных, соединённые одиночными пробелами. Пример: массив из Dog, Cat, Dog даст "Woof Meow Woof". Пустой массив даст "". Используйте цикл и вызывайте speak() — пусть полиморфизм подберёт правильный звук.
Click Run to see the output here. · Нажмите Запустить, чтобы увидеть результат здесь.
Animal, Dog, Cat, and a working Zoo.chorus are written for you. Add a class Cow that extends Animal and overrides speak() to return "Moo". Notice the existing chorus loop handles your new Cow with no changes. · Классы Animal, Dog, Cat и рабочий метод Zoo.chorus написаны за вас. Добавьте класс Cow, который наследует Animal и переопределяет speak() для возврата "Moo". Заметьте, что существующий цикл в chorus обработает вашего нового Cow без изменений.
Click Run to see the output here. · Нажмите Запустить, чтобы увидеть результат здесь.
Complete Fraction by overriding toString() so it returns the fraction as "numerator/denominator" — for 3 and 4 it returns "3/4". Java calls toString() automatically when you print a Fraction or join it with +. · Заполните Fraction, переопределив toString() так, чтобы он возвращал дробь как "numerator/denominator" — для 3 и 4 он вернёт "3/4". Java вызывает toString() автоматически при выводе объекта Fraction или его конкатенации со строкой через +.
Click Run to see the output here. · Нажмите Запустить, чтобы увидеть результат здесь.