Vì không có ai trả lời câu hỏi, tôi nghĩ tôi sẽ tự mình giải quyết. Tôi sẽ phải có một chút triết lý.
Lập trình chung là tất cả về trừu tượng hóa các loại tương tự, mà không làm mất thông tin loại (đó là những gì xảy ra với đa hình giá trị hướng đối tượng). Để làm điều này, các loại nhất thiết phải chia sẻ một số loại giao diện (một tập hợp các hoạt động, không phải là thuật ngữ OO) mà bạn có thể sử dụng.
Trong các ngôn ngữ hướng đối tượng, các kiểu thỏa mãn một giao diện nhờ các lớp. Mỗi lớp có giao diện riêng, được định nghĩa là một phần của loại. Vì tất cả các lớp List<T>
chia sẻ cùng một giao diện, bạn có thể viết mã hoạt động bất kể T
bạn chọn loại nào. Một cách khác để áp đặt một giao diện là một ràng buộc kế thừa, và mặc dù cả hai có vẻ khác nhau, chúng giống nhau nếu bạn nghĩ về nó.
Trong hầu hết các ngôn ngữ hướng đối tượng, List<>
bản thân nó không phải là một loại thích hợp. Nó không có phương thức, và do đó không có giao diện. Chỉ có List<T>
điều đó có những điều này. Về cơ bản, về mặt kỹ thuật, các loại duy nhất bạn có thể trừu tượng hóa một cách có ý nghĩa là những loại có loại *
. Để sử dụng các loại loại cao hơn trong một thế giới hướng đối tượng, bạn phải ràng buộc các cụm từ theo cách phù hợp với hạn chế này.
Ví dụ, như đã đề cập trong các nhận xét, chúng tôi có thể xem Option<>
và List<>
dưới dạng "có thể ánh xạ", theo nghĩa là nếu bạn có chức năng, bạn có thể chuyển đổi Option<T>
thành một Option<S>
hoặc List<T>
thành một List<S>
. Hãy nhớ rằng các lớp không thể được sử dụng để trừu tượng trực tiếp trên các loại loại cao hơn, thay vào đó chúng ta tạo một giao diện:
IMappable<K<_>, T> where K<T> : IMappable<K<_>, T>
Và sau đó chúng tôi thực hiện giao diện trong cả hai List<T>
và Option<T>
như IMappable<List<_>, T>
và IMappable<Option<_>, T>
tương ứng. Những gì chúng tôi đã làm, là sử dụng các loại loại cao hơn để đặt các ràng buộc trên các loại thực tế (không phải loại cao hơn) Option<T>
và List<T>
. Đây là cách nó được thực hiện trong Scala, mặc dù tất nhiên Scala có các tính năng như đặc điểm, biến loại và các tham số ngầm làm cho nó biểu cảm hơn.
Trong các ngôn ngữ khác, có thể trừu tượng hóa trực tiếp trên các loại loại cao hơn. Trong Haskell, một trong những cơ quan quyền lực cao nhất trên các hệ thống loại, chúng ta có thể cụm từ một loại loại cho bất kỳ loại nào, ngay cả khi nó có loại cao hơn. Ví dụ,
class Mappable mp where
map :: mp a -> mp b
Đây là một ràng buộc được đặt trực tiếp trên một loại (không xác định) mp
có một tham số loại và yêu cầu nó được liên kết với hàm map
biến một mp<a>
thành một mp<b>
. Sau đó, chúng ta có thể viết các hàm ràng buộc các loại loại cao hơn Mappable
giống như trong các ngôn ngữ hướng đối tượng, bạn có thể đặt một ràng buộc kế thừa. Vâng, loại.
Tóm lại, khả năng sử dụng các loại loại cao hơn của bạn phụ thuộc vào khả năng của bạn để hạn chế chúng hoặc sử dụng chúng như một phần của các ràng buộc loại.