Kế thừa và đa hình trong Java

Chào các anh ạ, em có câu hỏi sau.

Giả sử em có một class Quân Cờ (Em xin phép gõ theo kiểu tiếng Việt cho dễ đọc, dễ hiểu ạ), và class Quân Xe được kế thừa từ Quân Cờ.

2 class trên đều có một method tên là Đi().

Vậy em hiểu như này có đúng không ạ:

Quân Cờ a = new Quân Cờ();
a.Đi();

=> Cái này sẽ gọi method đi trong Quân Cờ.

Quân cờ b = new Quân Xe();
b.Đi();

=> Cái này sẽ gọi method đi trong Quân Xe.

Vậy cách khai báo Quân cờ b = new Quân Xe(); có tác dụng gì vì nếu b chỉ sử dụng được đi trong Quân Xe thì sao không khai báo luôn là: Quân Xe b = new Quân Xe(); mà lại dùng cách kia cho phức tạp ạ.

Đúng hơn là Quân Xe b = new Quân Cờ();
có 2 cách khai báo biến Quân Xe

  1. Quân Xe b = new Quân Cờ(); ==> vì Quân Xe “ăn bám” Quân Cờ
    Biến b CHỈ CÓ THỂ sử dụng các property, method được khai báo trong Quân Cờ (vì nó được khởi tạo từ Quân Cờ)
  2. Quân Xe b = new Quân Xe(); ==> cái này ai cũng biết :slight_smile:
    Biến b CÓ THỂ sử dụng các property, method được khai báo trong Quân Cờ trong Quân Xe vì b được khởi tạo từ Quân Xe nên có các method đã được implement tại Quân Cờ và tại Quân Xe

Anh nhầm ạ, phải là

Quân Cờ b = new Quân Xe(); chứ ạ?

Tại mình hay code như vậy :slight_smile: Để chống bug thôi :slight_smile:

Hình như có gì đó không đúng ở đây

2 Likes

Cái này gọi là tính đa hình (Polymorphism) trong OOP. Tác dụng của nó là giúp b được hệ thống coi như là 1 Quân Cờ nhưng nó lại có những tính chất của Quân Xe. Bạn có thể đọc thêm về tác dụng của tính đa hình tại đây:

1 Like

Bạn có nhầm lẫn ở đâu không. Quân xe có thể được coi là một Quân cờ nhưng mà Quân cờ không thể được coi là 1 Quân xe nhé :wink: Nếu bạn khai báo như vậy sẽ có bug ngay nhé :smile: Chứ không phải chống bug đâu :smile:

1 Like

:thinking:
Quay lại câu hỏi của chủ thớt, nếu như biến b không bị gán lại thì đúng là không cần khai báo như thế, tuy nhiên nếu trong hàm hoặc đối tượng, khi thực hiện công việc nào đó mà người ta muốn gán b = new Quân Mã(); thì làm thế nào?

Vì b có kiểu dữ liệu là Quân Cờ do bạn khai báo ở trên nên nó có thể gán vào lớp con bất kỳ của Quân Cờ, chứ nếu bạn gọi Quân Xe b = new Quân Xe(); từ đầu thì bạn không thể gán b cho một loại quân nào khác ngoài Quân Xe

Và nó cũng giúp cho code của bạn ngắn hơn, có thể cái này không đúng luật cờ vua, nhưng bạn có một việc gì đó muốn nhiều đối tượng cùng làm, hoặc một đối tượng làm nhưng không biết chính xác nó là đối tượng gì, mỗi đối tượng làm một kiểu nhưng công việc này là một hàm có kế thừa:

for (QuanCo a: getAllQuanCo())
	a.Đi();

Như vậy tất cả các quân cờ sẽ đi, dù là mỗi thằng đi 1 kiểu.

2 Likes
  1. Trói chặt logic vào class hơn :slight_smile: thay vì phải if thì chỉ cần khảo quân cờ “đi tới ô này” là được.
  2. Khi trói như vậy thì bổ sung con mới (hay đổi cách đi) dễ hơn.

Nhưng có cái bàn cờ vẫn tính dễ hơn.

2 Likes

giả sử khi em muốn ép kiểu sang quân tốt chẳng hạn, quân cờ có thể cast được, còn quân xe thì không. khai báo như thế tiện cho sử dụng về sau, khi chuyển đổi qua lại giữa class cha và con, sau này học spring càng hữu dụng hơn

Để phục vụ cho tính đa hình trong OOP thì Java cho phép làm như vậy. Điều này sẽ giúp cho tại những hoàn cảnh khác nhau, instance của class Quân Cờ sẽ được truyền vào những method Đi() tương ứng. Nếu instance của quân xe không bao giờ thay đổi thì cái được em gọi là viết cho đơn giản hoàn toàn đúng. Tuy nhiên phục vụ cho mục đích cao hơn là thiết kế, khi mà tại thời điểm viết, em vẫn chưa biết quân cờ của em nên có action Đi() như thế nào thì cách viết này sẽ giúp cho em linh hoạt hơn, tiết kiệm công sức viết code hơn vì code có thể dùng lại được.

2 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?