Hệ thống kiểu

Trong ngôn ngữ lập trình, hệ thống kiểu (tiếng Anh: "type system") là một tập các quy tắc gán một thuộc đặc tính gọi là kiểu cho các cấu trúc khác nhau của một chương trình máy tính bao gồm, như biến, biểu thức, hàm hay mô đun.
Những kiểu này chính thức hóa và bắt buộc (một cách ngầm định) các loại mà lập trình viên sử dụng cho cấu trúc dữ liệu và thành phần, ví dụ như: "chuỗi" ("string"), "mảng số thực" ("array of float"), "hàm trả về giá trị boolean"). Mục đích chính của hệ thống kiểu là để giảm khả năng lỗi trong chương trình máy tính bằng cách định nghĩa giao diện giữa các phần của chương trình máy tính, và sau đó kiểm tra các bộ phận được kết nối theo một cách nhất quán. Kiểm tra có thể xảy ra tĩnh (vào thời gian biên dịch - "compile time"), động (vào thời gian chạy -- "run time"), hay là sự kết hợp của kiểm tra tĩnh và động. Hệ thống kiểu còn có mục đích khác, như cho phép tối ưu hóa trình biên dịch nhất định, cho phép đa điều phối ("multiple dispatch"), cung cấp một dạng tài liệu...
Một hệ thống kiểu liên kết mỗi kiểu với một giá trị tính toán, bằng cách kiểu tra dòng của những giá trị đó, cố gắng bảo đảm hay chứng minh rằng không có lỗi kiểu nào có thể xảy ra. Hệ thống kiểu đã cho xác định chính xác những gì cấu thành lỗi kiểu, nhưng nói chung mục đích là để ngăn các toán tử sử dụng được những loại giá trị mà hoạt động tính toán trên đó không có ý nghĩa (lỗi logic); lỗi bộ nhớ cũng sẽ được ngăn chặn. Hệ thống kiểu thường được đặc tả như là một phần của ngôn ngữ lập trình, và xây dựng trong trình thông dịch và trình biên dịch của ngôn ngữ đó; mặc dù hệ thống kiểu của nogon ngữ có thể được mở rộng bởi các công cụ tùy chọn ("extended static checking") để thực hiện các loại kiểm tra bổ sung sử dụng cú pháp và ngữ pháp kiểu gốc của ngôn ngữ đó.
Tổng quan về sử dụng.
Một ví dụ về hệ thống kiểu đơn giản là về ngôn ngữ C. Một phần của một chương trình C là về định nghĩa hàm. Một hàm được gọi bởi hàm khác. Giao diện của một hàm mô tả tên của hàm và danh sách các giá trị được truyền vào trong mã của nó. Mã của hàm được gọi mô tả tên được gọi, cùng với tên các biến nắm giữ giá trị được truyền vào nó. Trong quá trình thực thi, những giá trị được đặt vào bộ nhớ tạm, rồi thực thi nhảy tới mã của hàm được gọi. Mã của hàm được gọi truy xuất những giá trị đó và sử dụng chúng. Nếu các lệnh bên trong hàm được viết với giả thiết nhận được giá trị số nguyên ("integer"), nhưng mã được gọi truyền đến một giá trị dấu chấm động ("floating-point"), như vậy kết quả sai sẽ được trả về bởi hàm được gọi. Bộ biên dịch C kiểm tra kiểu được định nghĩa cho mỗi biến được gửi đi, với kiểu được định nghĩa trong giao diện của hàm được gọi. Nếu các kiểu không khớp, trình biên dịch sẽ trả ra một lỗi biên dịch ("compile-time error").
Một trình biên dịch cũng có thể sử dụng kiểu tĩnh của giá trị để tối ưu hóa bộ nhớ cần thiết và chọn lựa giải thuật để hoạt động trên giá trị đó. Trong nhiều trình biên dịch của C, ví dụ như kiểu dữ liệu "số thực" ("float"), được biểu diễn bằng 32 bit, theo như đặc tả IEEE cho con số dấu chấm động chính xác đơn. Do vậy họ sẽ dùng các toán tử vi xử lý chuyên cho dấu chấm động (ví dụ như phép cộng, phép nhân dấm chấm động...).
Cơ bản.
Hiểu một cách chính thức thì lý thuyết kiểu nghiên cứu về hệ thống kiểu. Một ngôn ngữ lập trình phải có kiểm tra kiểu ("type check") bằng cách sử dụng "hệ thống kiểu" cho dù ở thời gian biên dịch hay thời gian chạy, ghi chú thủ công hay tự động suy ra. Như Mark Manasse đã nói rõ rằng:
Cho dù là được tự động bởi trình biên dịch hay được đặc tả bởi lập trình viên, hệ thống kiểu sẽ khiến hành vi chương trình trở nên bất hợp pháp nếu nó nằm ngoài quy tắc hệ thống kiểu. Ưu điểm của hệ thống kiểu đặc tả bởi lập trình viên gồm:
Ưu điểm của hệ thống kiểu đặc tả bởi trình biên dịch gồm:
Kiểm tra kiểu.
Quán trình kểm tra và thực thi các ràng buộc của kiểu—"kiểm tra kiểu" ("type checking")— có thể xảy ra ở thời gian biên dịch (kiểm tra tĩnh) hoặc thời gian chạy. Nếu một đặc tả ngôn ngữ yêu cầu các quy tắc kiểu mạnh (ví dụ, chỉ cho phép ít hay nhiều việc chuyển đổi kiểu tự động mà không làm mất thông tin), quá trình đó gọi là "kiểu mạnh", còn không, gọi là "kiểu yếu". Các thuật ngữ này thường không được dùng theo nghĩa chặt chẽ.
Kiểm tra kiểu tĩnh.
Kiểm tra kiểu tĩnh ("static type checking") là quá trình xác minh an toàn kiểu của một chương trình dựa vào sự phân tích văn bản (mã nguồn) của chương trình. Nếu một chương trình vượt qua được bộ kiểm tra kiểu tĩnh, khi đó chương trình đảm bảo đáp ứng được một số đặc tính an toàn cho tất cả đầu vào.
Kiểm tra kiểu động và thông tin kiểu thời gian chạy.
Kiểm tra kiểu động ("dynamic type checking") là quá trình xác minh an toàn kiểu của chương trình vào thời gian chạy.
Kết hợp kiểm tra kiểu tĩnh và động.
Một số ngôn ngữ cho phép cả kiểm tra kiểu tĩnh và động, đôi khi gọi là kiểm tra kiểu "mềm" ("soft typing").
Kiểm tra kiểu tĩnh và động trong thực tế.
Cần sự đánh đổi nhất định khi lựa chọn giữa kiểm tra kiểu tĩnh và động.
Các mức độ kiểm tra kiểu.
Một số ngôn ngữ cho phép các mức độ kiểm tra kiểu khác nhau áp dụng cho từng vùng mã khác nhau.
Hệ thống kiểu tùy chọn.
Nó được đề xuất chủ yếu bởi Gilad Bracha, cho phép lựa chọn hệ thống kiểu có thể độc lập với lựa chọn ngôn ngữ; như vậy một hệ thống kiểu nên là một mô đun để có thể "gắn" vào một ngôn ngữ khi cần.