[Object-Oriented + Ada] Bài 3 – Polymorphism & Type’Class

Lúc này chúng ta có trường Name và phương thức Greet của Coder đã được kế thừa lại từ Person, nhưng lại chỉ có thể hoạt động tốt nếu như object được truyền vào ở vị trí tham số thứ hai là kiểu Person.Entity; Còn nếu là kiểu Coder.Entity thì trình biên dịch sẽ báo

Lúc này chúng ta có trường Name và phương thức Greet của Coder đã được kế thừa lại từ Person, nhưng lại chỉ có thể hoạt động tốt nếu như object được truyền vào ở vị trí tham số thứ hai là kiểu Person.Entity; Còn nếu là kiểu Coder.Entity thì trình biên dịch sẽ báo lỗi chứ không có sự chuyển đổi kiểu dữ liệu ngầm định được thực hiện.

Như vậy là chúng ta đang cần thêm khả năng định kiểu dữ liệu cho một biến có thể đại diện được cho bất kỳ kiểu object nào trong cùng cây phả hệ hay hệ thống kế thừa. Và đây là một sự biểu thị của Tính Đa Hình Encapsulation, hay chính xác hơn là Sub-typing Polymorphism. Các kiểu Polymorphism còn lại không thuộc về OOP nói riêng thì chúng ta đã nói đến ở bài viết về Overloading Sub-programGenerics trong Sub-Series Procedural trước đó.

Type’Class

Khi sử dụng thuộc tính Class được gắn với các kiểu dữ liệu bằng cú pháp Type'Class thì chúng ta sẽ nhận được một kiểu dữ liệu tổng hợp Union biểu trưng cho tất cả các kiểu tagged trong cùng mô hình cây kế thừa tính từ vị trí của chính kiểu Type đó.

Ví dụ nếu chúng ta sử dụng Person.Entity'Class để định kiểu cho một biến nào đó thì biến đó sẽ có thể nhận lưu một object thuộc kiểu Person.Entity hoặc tất cả các kiểu trong dòng kế thừa tính từ Person.Entity trở đi.

Vậy nếu như chúng ta sửa lại định nghĩa của phương thức Greet trong package Person với tham số đứng sau sử dụng kiểu Person.Entity'Class thì chúng ta sẽ có thể sử dụng một object Person.Entity để Greet một object Coder.Entity mà không gặp phải thông báo lỗi.

package Person is

   type Entity is tagged;
   type Class is access all Entity'Class;
   
   -- ...

   procedure Greet (Self: in Entity; Other: in Entity'Class);

end Person;

Ở đây chúng ta cũng đồng thời cập nhật định nghĩa của kiểu con trỏ Person.Class thành access all Entity'Class. Như vậy khi khởi tạo các object mới, chúng ta có thể sử dụng một biến con trỏ kiểu này để lưu các object Coder.Entity hoặc các kiểu khác trong cùng cây kế thừa nếu cần thiết.

Overriding Method

Nói về phương thức Greet được định nghĩa tại Person, tham số Other : in Entity'Class lúc này đã có khả năng biểu thị cho nhiều kiểu object khác nhau và như vậy chúng ta đã có thể nói rằng đây là một biểu hiện của Tính Đa Hình Polymorphism. Tuy nhiên để biểu thị ở bề mặt kết quả hoạt động thì chúng ta có thể sẽ muốn cung cấp thêm một phiên bản định nghĩa mở rộng của Greet trong Coder.

with Person; use Person;

package Person.Coder is

   -- ...
   
   procedure Greet (Self: in Entity; Other: in Person.Entity'Class);

end Person.Coder;

Giả sử hành động Greet ở đây, chúng ta sẽ chỉ cần sử dụng thêm duy nhất tên của người đối diện trong câu chào "Hi, " & Other.Name. Nếu vậy kiểu object mô phỏng người đối diện sẽ chỉ cần có ít nhất trường Name đã được định nghĩa tại Person và vì vậy nên để có logic hoạt động đầy đủ nhất chúng ta có thể định kiểu tham số OtherPerson.Entity'Class.

with Ada.Text_IO; use Ada.Text_IO;
with Person; use Person;

package body Person.Coder is

   procedure Greet
      ( Self : in Entity
      ; Other : in Person.Entity'Class )
   is -- local
   begin
      Person.Entity (Self).Greet (Other);
      Put_Line ("A fellow Coder");
   end Greet;

end Person.Coder;

Để gọi tới định nghĩa của Greet đã có sẵn trong Person thì ở đây chúng ta cần chuyển kiểu của Self thành Person.Entity qua thao tác như trên. Và lúc này chúng ta đã có thể thử lại code tương tác tại main, lần này chúng ta sẽ thử sử dụng kiểu con trỏ Person.Class thay cho Coder.Class của biến Me để kiểm tra luôn hoạt động của kiểu con trỏ access all Person.Entity'Class.

with Ada.Text_IO; use Ada.Text_IO;
with Person; use Person;
with Person.Coder; use Person.Coder;

procedure Main is
   Me, Lucy : Person.Class;
begin
   Me := new Coder.Entity'
      ( Name => "Semi Dev_   "
      , Intellect => 0 );

   Lucy := new Person.Entity'
      ( Name => "Lucy        " );

   Put_Line ("-- Message - - - -");
   Me.Greet (Lucy.all);

   Put_Line ("-- Message - - - -");
   Lucy.Greet (Me.all);
end Main;
alr run

-- Message - - - -
Hi, Lucy
I'm Semi Dev_
A fellow Coder
-- Message - - - -
Hi, Semi Dev_
I'm Lucy

[Object-Oriented + Ada] Bài 4 – Abstraction & Inteface

Nguồn: viblo.asia

Bài viết liên quan

Thay đổi Package Name của Android Studio dể dàng với plugin APR

Nếu bạn đang gặp khó khăn hoặc bế tắc trong việc thay đổi package name trong And

Lỗi không Update Meta_Value Khi thay thế hình ảnh cũ bằng hình ảnh mới trong WordPress

Mã dưới đây hoạt động tốt có 1 lỗi không update được postmeta ” meta_key=

Bài 1 – React Native DevOps các khái niệm và các cài đặt căn bản

Hướng dẫn setup jenkins agent để bắt đầu build mobile bằng jenkins cho devloper an t

Chuyển đổi từ monolith sang microservices qua ví dụ

1. Why microservices? Microservices là kiến trúc hệ thống phần mềm hướng dịch vụ,