Polymorphism: dynamic dispatch and toString() · Đa hình: phân phối động và 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.
Polymorphism: một type, nhiều hành vi
- Polymorphism có nghĩa là "nhiều hình thái": một type superclass, nhiều hành vi subclass.
- Bạn có thể lưu trữ một
Doghoặc mộtCattrong biếnAnimal, vì mỗi loại đều là mộtAnimal. - Khi bạn gọi một method, type thật của đối tượng quyết định phiên bản nào được chạy.
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.
Phân phối động
- Kiểu của biến (
Animal) quyết định những phương thức bạn được phép gọi. - Nhưng khi chạy, đối tượng thực tế (
Dog) quyết định phiên bản nào bị ghi đè sẽ được thực thi. - Sự lựa chọn này khi chạy được gọi là phân phối động — đây là trái tim của đa hình.
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.
Một vòng lặp xử lý mọi lớp con
- Vòng lặp trên không bao giờ hỏi "đây là Dog hay Cat?" — nó chỉ gọi
speak(). - Mỗi đối tượng trả lời theo cách riêng của nó. Điều đó giữ cho vòng lặp ngắn gọn và tổng quát.
- Thêm một lớp con mới sau này và vòng lặp giống nhau vẫn hoạt động trên nó mà không cần thay đổi.
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(): mọi đối tượng đều kế thừa nó từ Object
- Mọi class trong Java ngầm mở rộng một class có tên là
Object, class này có mộttoString(). - Ghi đè
toString()để nói cách đối tượng của bạn nên hiển thị dưới dạng văn bản. - Java gọi nó tự động khi bạn in một đối tượng hoặc ghép nó với
+.
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.
Lỗi thường gặp
- Phương thức của đối tượng thực tế chạy khi thực thi (phân phối động), không phải kiểu của biến.
- Ghi đè
toString()để có đầu ra dễ đọc.
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.
Bây giờ bạn thử
- Sử dụng mảng superclass, thêm một subclass mới, và ghi đè
toString(). - Một Harness ẩn kiểm tra xem phiên bản đúng có chạy cho mỗi đối tượng hay không.
- Nhấn Run để biên dịch, sau đó Check answer. Mã của bạn chạy trên server, vì vậy ngay cả lần chạy đầu tiên cũng rất nhanh.
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 và Cat đã được viết sẵn. Hoàn thiện phương thức tĩnh Zoo.chorus(Animal[] animals) sao cho trả về âm thanh của mọi động vật được nối bằng khoảng trắng đơn. Ví dụ: mảng Dog, Cat, Dog sẽ tạo ra "Woof Meow Woof". Mảng rỗng tạo ra "". Lặp qua và gọi speak()—học đa hình sẽ chọn đúng âm thanh.
Click Run to see the output here. · Nhấn Chạy để xem kết quả ở đây.
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 và một Zoo.chorus hoạt động đã được viết sẵn. Thêm class Cow kế thừa từ Animal và ghi đè speak() để trả về "Moo". Notice rằng vòng lặp chorus hiện tại xử lý Cow mới của bạn mà không cần thay đổi.
Click Run to see the output here. · Nhấn Chạy để xem kết quả ở đây.
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 +. · Hoàn thiện Fraction bằng cách ghi đè toString() để trả về phân số dưới dạng "numerator/denominator"—đối với 3 và 4 nó sẽ trả về "3/4". Java tự động gọi toString() khi bạn in một Fraction hoặc ghép nó với +.
Click Run to see the output here. · Nhấn Chạy để xem kết quả ở đây.