Toán tử nhiệm mầu
Hãy tưởng tượng ta làm một ứng dụng (như là phần mềm cho vệ tinh viễn thám chẳng hạn
) tính diện tích các vùng lãnh thổ nào đó. Ta muốn thiết lập ràng buộc theo tinh thần các định luật vật lý.
Code: type Metres is new Float;
type Metres_vuong is new Float;
Nếu lúc này ta muốn tính một diện tích thì ta buộc phải đổi kiểu tường minh; lối viết này có đôi phần khiếm nhã.
Code: declare
chieu_dai : Metres := 10.0;
chieu_rong : Metres := 15.0;
dien_tich : Metres_vuong;
begin
dien_tich := Metres_vuong (chieu_dai * chieu_rong); -- buộc phải đổi kiểu
end;
Rõ ràng ta biết rằng khi nhân mét với mét ta sẽ thu được mét vuông. Chẳng lẽ không có cách nào khéo léo đưa quy tắc đó vào ngôn ngữ? Có đấy! Ta giải quyết chuyện này bằng cách
quá tải (overload) toán tử nhân cho kiểu Metres, sao cho kết quả là Metres_vuông:
Code: function "*" (Left, Right : Metres) return Metres_vuong is
begin
return Metres_vuong(Float(Left)*Float(Right)); -- Float để tránh đệ quy
end;
Trong đoạn mã trên trước khi nhân ta đổi kiểu sang Float để tránh đệ quy. Khi bộ biên dịch dùng phép nhân Float, mọi chuyện đều ổn cả.
Giờ đây, không những khi tính diện tích ta không cần đổi kiểu nữa, mà thậm chí rất đúng ý ta, bộ biên dịch còn phát hiện được lỗi ở đoạn mã sai thứ nguyên vật lý sau đây.
Code: declare
chieu_dai : Metres := 10.0;
chieu_rong : Metres := 15.0;
dien_tich : Metres;
begin
dien_tich := chieu_dai * chieu_rong; -- lỗi ngữ nghĩa tĩnh
end;
Để có những kết cấu kiểm tra kiểu mạnh đó, cái giá phải trả là bao nhiêu?
Nhiều người hẳn sẽ phản đối rằng với các kết cấu đó, mã đích phải rất dài và rất chậm. Họ đã nghĩ sai. Hàng loạt phép kiểm tra được thực hiện khi biên dịch mã nguồn. Phép kiểm tra khi chạy (run-time) chỉ có mặt ở những nơi nào cần thiết. Dễ thấy rằng nếu gán một biến số tự nhiên vào một biến số nguyên thì chẳng cần phải kiểm tra gì bởi vì các số tự nhiên là tập con của các số nguyên. Hơn nữa, mã nguồn càng chứa nhiều ràng buộc thì bộ biên dịch càng có nhiều thông tin để thi triển các chiêu thức tối ưu hóa mức cao. Bộ biên dịch GNAT được xây dựng trên back-end GCC, cho nên nó cũng biết hết cả các chiêu thức tối ưu hóa mức thấp. Về tốc độ chạy, các chương trình Ada hoàn toàn có thể sánh vai được với các chương trình C/C++. Các bộ xử lý ngày nay đều có mã lệnh (instruction) đặc biệt để kiểm tra ràng buộc khoảng số nguyên, nhờ vậy phí tổn cho việc đó trong những ứng dụng đời thực chỉ đáng vài phần trăm mà thôi. Nói cho cùng, ngày nay các phép tính số học thực hiện rất nhanh cả trong ngôn ngữ Java và C# cơ mà.