Mỗi lần như vậy, tôi làm cho một giao diện đơn giản phức tạp hơn bằng cách thêm ràng buộc tham số kiểu tự tham chiếu ("phản xạ") vào nó. Ví dụ, tôi có thể tắt chức năng này:Ràng buộc tham số kiểu phản xạ: X <T> trong đó T: X <T> - bất kỳ lựa chọn thay thế đơn giản nào khác?
interface ICloneable
{
ICloneable Clone();
}
class Sheep : ICloneable
{
ICloneable Clone() { … }
} //^^^^^^^^^^
Sheep dolly = new Sheep().Clone() as Sheep;
//^^^^^^^^
thành:
interface ICloneable<TImpl> where TImpl : ICloneable<TImpl>
{
TImpl Clone();
}
class Sheep : ICloneable<Sheep>
{
Sheep Clone() { … }
} //^^^^^
Sheep dolly = new Sheep().Clone();
lợi thế chính: Loại thực hiện (chẳng hạn như Sheep
) bây giờ có thể tham khảo bản thân thay vì kiểu cơ sở của nó, làm giảm nhu cầu loại đúc (như được chứng minh bởi dòng cuối cùng của mã).
Trong khi điều này rất hay, tôi cũng nhận thấy rằng các ràng buộc tham số kiểu này không trực quan và có xu hướng trở nên thực sự khó hiểu trong các tình huống phức tạp hơn. *)
Câu hỏi: Có ai biết của một mã mẫu C# mà đạt được tác dụng tương tự hoặc một cái gì đó tương tự, nhưng trong một thời trang dễ dàng hơn để nắm bắt?
*) mẫu mã này có thể unintuitive và khó hiểu ví dụ trong các cách sau: "Nếu
T
là mộtX<T>
, sau đóX<T>
thực sự là mộtX<X<…<T>…>>
"
Việc kê khai
X<T> where T : X<T>
dường như là đệ quy, và người ta có thể tự hỏi tại sao các trình biên dịch doesn't get stuck in an infinite loop, lý luận, (Nhưng những hạn chế rõ ràng là không được giải quyết như thế.)Đối với cơ quan thực hiện, nó có thể không được rõ ràng những gì loại nên được chỉ định vào vị trí của
TImpl
. (Các ràng buộc cuối cùng sẽ chăm sóc đó.)Khi bạn thêm thông số loại khác và phân loại các mối quan hệ giữa các giao diện chung khác nhau với kết hợp, mọi thứ sẽ không thể quản lý được một cách nhanh chóng.
Bạn sẽ rất vui khi biết rằng điều này đủ phổ biến để có tên: Nó được gọi là 'Mẫu mẫu tò mò định kỳ' (viết tắt là CRTP). – Cameron
... và không liên quan gì đến các ràng buộc (vì các mẫu C++ chuẩn không có chúng). – Krizz
Có lý do nào đó không chỉ là 'giao diện ICloneable {T Clone(); } '? –