Mục đích của tài liệu tham khảo rõ ràng này trong C # là gì?


21

Tôi đang đánh giá một CMS nguồn mở có tên là Piranha ( http://piranhacms.org/ ) để sử dụng trong một trong các dự án của tôi. Tôi thấy đoạn mã sau thú vị và hơi khó hiểu, ít nhất là với tôi. Một số có thể giúp tôi hiểu tại sao lớp học được kế thừa từ một cơ sở cùng loại?

public abstract class BasePage<T> : Page<T> where T : BasePage<T>
{
    /// <summary>
    /// Gets/sets the page heading.
    /// </summary>
    [Region(SortOrder = 0)]
    public Regions.PageHeading Heading { get; set; }
}

Nếu một lớp BasePage<T>đang được định nghĩa, tại sao lại kế thừa từ Page<T> where T: BasePage<T>? Mục đích cụ thể nào nó phục vụ?



7
Mặc dù có nhiều lượt bình chọn và bỏ phiếu chặt chẽ, tôi nghĩ cộng đồng đã hiểu sai về điều này. Đây là một câu hỏi được nêu rõ ràng phải làm với một quyết định thiết kế cụ thể và không tầm thường, bản chất của những gì trang web này là về.
Robert Harvey

Chỉ quanh quẩn và mở lại khi nó bị đóng cửa.
David Arno

Đọc về khái niệm đa hình giới hạn F :)
Eyvind

1
@Eyvind Tôi thực sự đã làm. Đối với những người thích đọc về đa hình F-Bounded, đây là link staff.ustc.edu.cn/~xyfeng/teaching/FOPL/lectureNotes/iêu
Xami Yen 2/11/18

Câu trả lời:


13

Một số có thể giúp tôi hiểu tại sao lớp học được kế thừa từ một cơ sở cùng loại?

Không phải, nó được thừa hưởng từ Page<T>, nhưng Tbản thân nó bị hạn chế để được tham số hóa bởi một loại có nguồn gốc từ BasePage<T>.

Để suy luận tại sao, bạn phải xem cách tham số loại Tthực sự được sử dụng. Sau khi đào bới, khi bạn tiến lên chuỗi thừa kế, bạn sẽ đến lớp này:

( github )

public class GenericPage<T> : PageBase where T : GenericPage<T>
{
    public bool IsStartPage {
        get { return !ParentId.HasValue && SortOrder == 0; }
    }

    public GenericPage() : base() { }

    public static T Create(IApi api, string typeId = null)
    {
        return api.Pages.Create<T>(typeId);
    }
}

Theo như tôi có thể thấy, mục đích duy nhất cho ràng buộc chung là để đảm bảo rằng Createphương thức trả về loại trừu tượng nhất có thể.

Dù không chắc là nó có đáng hay không, nhưng có lẽ có lý do chính đáng nào đó đằng sau nó, hoặc có thể chỉ vì sự thuận tiện, hoặc có thể không có quá nhiều chất đằng sau nó và đó chỉ là một cách quá phức tạp để tránh diễn viên (BTW, I Tôi không ngụ ý đó là trường hợp ở đây, tôi chỉ nói rằng mọi người đôi khi làm điều đó).

Lưu ý rằng điều này không cho phép họ để tránh phản chiếu - sự api.Pageslà một kho lưu trữ các trang mà có được typeof(T).Name, và vượt qua nó như là typeIdđể các contentService.Createphương pháp ( xem tại đây ).


5

Một cách sử dụng phổ biến này có liên quan đến khái niệm tự loại: một tham số loại phân giải thành loại hiện tại. Giả sử bạn muốn xác định một giao diện với một clone()phương thức. Các clone()phương pháp phải luôn trả về một thể hiện của lớp mà nó được gọi. Làm thế nào để bạn tuyên bố phương pháp đó? Trong một hệ thống chung có loại tự, thật dễ dàng. Bạn chỉ cần nói nó trở lại self. Vì vậy, nếu tôi có một lớp Foo, phương thức nhân bản phải được khai báo để trả về Foo. Trong Java và (từ một tìm kiếm chữ thảo) C #, đây không phải là một tùy chọn. Thay vào đó, bạn thấy các khai báo như những gì bạn thấy trong lớp này. Điều quan trọng là phải hiểu rằng đây không giống như kiểu tự và các hạn chế mà nó cung cấp yếu hơn. Nếu bạn có một Foovà một Barlớp mà cả hai đều xuất phát từBasePage, bạn có thể (nếu tôi không nhầm) định nghĩa Foo sẽ được tham số hóa bởi Bar. Điều đó có thể hữu ích nhưng tôi nghĩ, thông thường, phần lớn thời gian, nó sẽ được sử dụng như kiểu tự và nó chỉ hiểu rằng mặc dù bạn có thể đi vòng quanh và thay thế bằng các loại khác, nhưng đó không phải là điều bạn nên làm. Tôi đã chơi xung quanh với ý tưởng này từ lâu nhưng đã đi đến kết luận rằng nó không đáng để nỗ lực vì những hạn chế của khái quát Java. Thuốc generic C # tất nhiên có đầy đủ tính năng hơn nhưng dường như cũng có giới hạn này.

Một lần khác, cách tiếp cận này được sử dụng là khi bạn đang xây dựng các loại giống như biểu đồ như cây hoặc các cấu trúc đệ quy khác. Tuyên bố cho phép các loại đáp ứng các yêu cầu của Trang nhưng tinh chỉnh thêm loại. Bạn có thể thấy điều này trong một cấu trúc cây. Ví dụ, một cái Nodecó thể được tham số hóa bằng cách Nodecho phép các triển khai xác định rằng chúng không chỉ là Cây chứa bất kỳ loại Nút nào mà là một loại Nút phụ cụ thể (thường là loại riêng của chúng.) Tôi nghĩ đó là những gì đang diễn ra ở đây.


3

Là người thực sự đã viết mã, tôi có thể xác nhận rằng Filip là chính xác và chung chung tự tham chiếu thực sự là một sự tiện lợi cho việc cung cấp một phương thức Tạo được gõ trên lớp cơ sở.

Giống như ông đề cập, vẫn còn rất nhiều sự phản ánh đang diễn ra, và cuối cùng chỉ có tên của loại được sử dụng để giải quyết loại trang. Lý do cho điều này là bạn cũng có thể tải các mô hình động, tức là cụ thể hóa mô hình mà không có quyền truy cập vào loại CLR đã tạo ra nó ở vị trí đầu tiên.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.