You are on page 1of 6

15.

5 ● Polymorphism
15.5 ● Tính đa hình
Bomb to create two objects, storing them in an array list named game, and displaying
them. The display is shown in Figure 15.1.
"Dùng Bomb để tạo ra hai đối tượng, lưu trữ chúng trong một danh sách mảng có tên là game, và hiển thị
chúng:
Alien alien = new Alien(20, 20, 100);
Bomb bomb = new Bomb(80, 80, 10);
ArrayList game = new ArrayList();
game.add(alien);
game.add(bomb);
for (int s = 0; s < game.size(); s++) {
Object item = game.get(s);
Sprite sprite = (Sprite) item;
sprite.display(paper);
}
Hình 15.1
Polymorphism is in use here – the method display is called on two occasions with
different results according to which object is in use. You can see that the two calls of
display within the for loop:
sprite.display(paper);
give two different outputs. Two different outputs are displayed because the Java sys-
tem automatically selects the version of display associated with the class of the object.
When method display is first called, the variable sprite contains the object alien
and so the version of display in the class Alien is called. Then the corresponding
thing happens with bomb. This is the essence of polymorphism.
The class of an object is determined when the object is created using new classes,
and stays the same whatever happens to the object. Whatever you do to an object in a
program, it always retains the features it had when it was created. An object can be
assigned to a variable of another class and passed around the program as a parameter,
but it never loses its true identity.
Polymorphism allows us to write a single concise statement, such as:
"Đa hình được áp dụng ở đây - phương thức display được gọi hai lần với kết quả khác nhau tùy thuộc vào
đối tượng nào được sử dụng. Bạn có thể thấy rằng hai lần gọi display trong vòng lặp for:
sprite.display(paper);
cho hai kết quả khác nhau. Điều này xảy ra vì hệ thống Java tự động chọn phiên bản của display liên kết
với lớp của đối tượng.
Khi phương thức display được gọi lần đầu tiên, biến sprite chứa đối tượng alien, do đó phiên bản của
display trong lớp Alien được gọi. Sau đó, điều tương tự xảy ra với bomb. Đây là bản chất của đa hình.
Lớp của một đối tượng được xác định khi đối tượng được tạo bằng cách sử dụng new, và luôn giữ nguyên
bất kể điều gì xảy ra với đối tượng. Bất kỳ thay đổi nào bạn thực hiện trên một đối tượng trong chương
trình, nó luôn giữ nguyên các đặc điểm mà nó có khi nó được tạo. Một đối tượng có thể được gán cho một
biến của một lớp khác và được truyền xuyên suốt chương trình như một tham số, nhưng nó không bao giờ
mất đi danh tính thực sự của nó.
Đa hình cho phép chúng ta viết một câu lệnh ngắn gọn duy nhất, như sau:
sprite.display(paper);
instead of a series of if statements like this:
if (sprite instanceof Alien) {
Alien alien = (Alien) sprite;
alien.display(paper);
}
if (sprite instanceof Bomb) {
Bomb bomb = (Bomb) sprite;
bomb.display(paper);
}

15.5 Polymorphism 211


which is clumsy and long-winded. This uses the keyword instanceof to ask if an
object is a member of a named class. If there are a large number of graphical objects,
there are a correspondingly large number of if statements. Avoiding this complexity
demonstrates how powerful and concise polymorphism is.
As we have seen in this small example, polymorphism often makes a segment of pro-
gram smaller and neater through the elimination of a series of if statements. But this achievement is much
more significant than it may seem. It means that such statements as:
sprite.display(paper);
know nothing about the possible variety of objects that may be used as the value of

sprite. So information hiding (already present in large measure in an OOP) is extend-


ed. We can check this by assessing how much we would need to change this program

to accommodate some new type of graphical object (some additional subclass of


Sprite), say a laser. The answer is that we would not need to modify it at all – we could
simply add the new object. This means that the program is enormously flexible. Thus
polymorphism enhances modularity, reusability and maintainability.
Polymorphism helps construct programs that are:
■ concise (shorter than they might otherwise be)
■ modular (unrelated parts are kept separate)
■ easy to change and adapt (for example, introducing new objects).
In general, the approach to exploiting polymorphism within a particular program is
as follows:
1. identify any similarities (common methods and variables) between any objects or
classes in the program
2. design a superclass that embodies the common features of the classes
3. design the subclasses that describe the distinctive features of each of the classes,
whilst inheriting the common features from the superclass
4. identify any place in the program where the same operation must be applied to any
of the similar objects. It may be tempting to use if statements at this location.
Instead, this is the place to use polymorphism.
5. make sure that the superclass contains an abstract method corresponding to the
method that is to be used polymorphically.
The code fragment shown above, with an array list and a for loop, is an example of
a commonly occurring situation in software, where the entire contents of a collection

are processed. It is so common that some languages provide a foreach control struc-
ture. In Java, the above for loop can be rewritten more concisely as:

Đa hình 15.5
một phần của mã lập trình mà không linh hoạt và dài dòng. Cụ thể, điều này sử dụng từ khóa instanceof
để hỏi xem một đối tượng có là thành viên của một lớp đã đặt tên hay không. Nếu có một số lượng lớn
các đối tượng đồ họa, sẽ có một số lượng if tương ứng lớn. Tránh sự phức tạp này thể hiện sức mạnh và
tính ngắn gọn của đa hình.
Như chúng ta đã thấy trong ví dụ nhỏ này, đa hình thường làm cho một phần của chương trình trở nên
nhỏ gọn và gọn gàng thông qua việc loại bỏ một loạt các câu lệnh điều kiện `if`. Nhưng thành tựu này
quan trọng hơn nhiều so với vẻ bề ngoài của nó. Điều này có nghĩa là các câu lệnh như:
sprite.display(paper);
không biết gì về các loại đối tượng có thể được sử dụng làm giá trị của `sprite`. Vì vậy, việc ẩn thông tin
(đã tồn tại ở mức lớn trong OOP) được mở rộng. Chúng ta có thể kiểm tra điều này bằng cách đánh giá
xem chúng ta sẽ cần phải thay đổi chương trình này như thế nào để phù hợp với một loại đối tượng đồ họa
mới (một lớp con bổ sung của Sprite), ví dụ như một tia laser. Câu trả lời là chúng ta không cần phải sửa
đổi nó chút nào - chúng ta chỉ cần thêm đối tượng mới. Điều này có nghĩa là chương trình cực kỳ linh
hoạt. Do đó, đa hình tăng cường tính mô đun, khả năng tái sử dụng và khả năng bảo trì.

Đa hình giúp xây dựng các chương trình:


- Ngắn gọn (ngắn hơn so với những gì nó có thể)
- Mô đun (phần không liên quan được giữ riêng biệt)
- Dễ thay đổi và điều chỉnh (ví dụ, giới thiệu các đối tượng mới).

Nói chung, cách tiếp cận sử dụng đa hình trong một chương trình cụ thể như sau:
1. Xác định bất kỳ sự tương đồng nào (phương thức và biến chung) giữa bất kỳ đối tượng hoặc lớp nào
trong chương trình.
2. Thiết kế một lớp cha mô tả các đặc điểm chung của các lớp.
3. Thiết kế các lớp con mô tả các đặc điểm độc đáo của mỗi lớp, trong khi kế thừa các đặc điểm chung từ
lớp cha.
4. Xác định bất kỳ nơi nào trong chương trình mà cùng một thao tác phải được áp dụng cho bất kỳ đối
tượng tương tự nào. Có thể rất hấp dẫn để sử dụng các câu lệnh điều kiện `if` tại vị trí này. Thay vào đó,
đây là nơi sử dụng đa hình.
5. Đảm bảo rằng lớp cha chứa một phương thức trừu tượng tương ứng với phương thức được sử dụng đa
hình.

Đoạn mã được hiển thị ở trên, với một danh sách mảng và một vòng lặp for, là một ví dụ về tình huống
thường xuyên xảy ra trong phần mềm, nơi toàn bộ nội dung của một bộ sưu tậpđược xử lý. Điều này rất
phổ biến đến mức một số ngôn ngữ cung cấp một cấu trúc điều khiển foreach.
Trong Java, vòng lặp for trên có thể được viết lại một cách ngắn gọn hơn như sau:
for (Object item : game) {
((Sprite) item).display(paper);
}
Each time that the for statement repeats, it obtains the next element from the array
list game.
Mỗi khi câu lệnh for lặp lại, nó lấy phần tử tiếp theo từ danh sách mảng game.

15.6 ● Single versus multiple inheritance


As we have seen, Java supports single inheritance – a class can inherit from only one
immediate superclass. Seen as a class diagram, the relationships between classes appear
as a tree (a computer science tree, with the root at the top). Smalltalk, Ada, C# and
Visual Basic.Net also provide single inheritance.
However, the widely used language C++ provides multiple inheritance, as does
Eiffel. In such a language, a class can inherit from not just one but several superclasses.
In life we are not just a person, we also belong to other categories, such as brothers,
daughters, soccer lovers, carnivores. So a class representing a person is a subclass of all
these superclasses, inheriting variables and methods from them all.
There is no doubt that multiple inheritance is more complicated – both to provide
in the language and to use. C++ was widely seen as an overcomplicated language and
subsequent languages, such as Java and C#, have seen simplifications in many areas,
including abandoning multiple inheritance in favor of single. In some languages,

including Java and C#, one role of multiple inheritance has been replaced by the inter-
face facility described in Chapter 16 on programming in the large.
15.6 ● Kế thừa đơn lẻ so với kế thừa đa lớp

Như chúng ta đã thấy, Java hỗ trợ kế thừa đơn lẻ - một lớp chỉ có thể kế thừa từ một lớp cha trực tiếp.
Nhìn như một biểu đồ lớp, các mối quan hệ giữa các lớp xuất hiện như một cây (một cây máy tính, với
gốc ở trên cùng). Smalltalk, Ada, C# và Visual Basic.Net cũng cung cấp kế thừa đơn lẻ.

Tuy nhiên, ngôn ngữ phổ biến được sử dụng rộng rãi là C++ cung cấp kế thừa đa lớp, cũng như Eiffel.
Trong một ngôn ngữ như vậy, một lớp không chỉ kế thừa từ một mà còn từ nhiều lớp cha. Trong cuộc
sống, chúng ta không chỉ là một người, chúng ta cũng thuộc về các danh mục khác nhau, như anh em, con
gái, người yêu bóng đá, động vật ăn thịt. Vì vậy, một lớp đại diện cho một người là một lớp con của tất cả
các lớp cha này, kế thừa các biến và phương thức từ tất cả chúng.

Không có nghi ngờ gì rằng kế thừa đa lớp phức tạp hơn - cả về việc cung cấp trong ngôn ngữ và sử dụng.
C++ thường được coi là một ngôn ngữ quá phức tạp và

1 số đoạn thêm pp:

You might also like