C #: Các lớp trừu tượng cần thực hiện giao diện?


131

Mã kiểm tra của tôi trong C #:

namespace DSnA
{
    public abstract class Test : IComparable
    {

    }
}

Kết quả trong lỗi trình biên dịch sau:

error CS0535: 'DSnA.Test' does not implement interface member
'System.IComparable.CompareTo(object)'

Vì lớp Testlà một lớp trừu tượng , tại sao trình biên dịch yêu cầu nó thực hiện giao diện? Không nên yêu cầu này chỉ bắt buộc đối với các lớp học cụ thể?


Haha. Tôi đã viết một điều sau đó quyết định thay đổi nó. Lấy làm tiếc. :)
Joel

2
Dựa trên các downvote và bình luận về câu trả lời được chấp nhận, tôi tin rằng các downvote đến vì cách mà câu hỏi được diễn đạt. OP hỏi "tại sao nó lại như vậy", nằm ngoài phạm vi của stackoverflow. Khi gặp phải điều này, câu hỏi giống như "Tôi có thiếu thứ gì không? Tôi có thực sự phải cung cấp các triển khai không? Không phải điều đó đánh bại quan điểm của nó là một lớp trừu tượng sao?" Câu trả lời là "Không, bạn không phải cung cấp các triển khai (sẽ vi phạm mục đích của một lớp trừu tượng), nhưng đây là những gì bạn phải làm, để làm cho tình huống của bạn hoạt động."
ToolmakerSteve

Tôi tìm thấy một trường hợp mà bạn phải cung cấp một triển khai. Đó là nơi giao diện có một tham số tùy chọn. Nếu bạn bao gồm phương thức là trừu tượng trong lớp cơ sở thì các lớp được kế thừa sẽ không biên dịch nếu không có tham số tùy chọn (đánh bại mục đích của tham số tùy chọn). Tôi chỉ ném NotImcellenceedException trong trường hợp này.
Paul McCarthy

Bỏ qua bình luận trước đây của tôi - nó không hoạt động như mong đợi, nguyên tắc ít bất ngờ nhất không được áp dụng ở đây.
Paul McCarthy

Câu trả lời:


141

Trong C #, một lớp thực hiện một giao diện được yêu cầu để xác định tất cả các thành viên của giao diện đó. Trong trường hợp của một lớp trừu tượng, bạn chỉ cần định nghĩa các thành viên đó bằng abstracttừ khóa:

interface IFoo
{
    void Bar();
}

abstract class Foo : IFoo
{
    public abstract void Bar();
}

Hoặc nói theo một cách khác: bạn không phải "thực hiện" nó (đó sẽ là một hạn chế khủng khiếp đối với các lớp trừu tượng); tuy nhiên, trong C #, bạn phải thông báo cho trình biên dịch rằng bạn đang cố tình chuyển buck cho các lớp con cụ thể - và dòng mã trên cho thấy cách thực hiện.

Các ý kiến ​​và downvote phàn nàn rằng đây không phải là một câu trả lời cho câu hỏi đang thiếu điểm. Ai đó đến với Stack Overflow, đã nhận được lỗi trình biên dịch này, nhưng có một lớp trừu tượng trong đó sẽ là một lỗi khi cung cấp một triển khai, bị mắc kẹt mà không có giải pháp tốt - sẽ phải viết các phương thức thực hiện đã ném ngoại lệ thời gian chạy, một công việc khủng khiếp -around - cho đến khi họ có thông tin trên. Cho dù đó là tốt hay xấu mà C # yêu cầu nhà thám hiểm này nằm ngoài phạm vi của Stack Overflow, và không liên quan đến câu hỏi cũng như câu trả lời này.


2
@Ben Chỉ cần xem bình luận của bạn. Bạn có thể đã tìm ra nó rồi, nhưng trong trường hợp người khác cần nó. Kiểm tra triển khai giao diện rõ ràng: msdn.microsoft.com/en-us/l Library / ms173157.aspx
Joel

2
@Joel @Ben Tôi không nghĩ các giao diện rõ ràng có thể hoạt động với các lớp trừu tượng. Trong mã ví dụ ở trên, thay đổi định nghĩa Foothành public abstract void IFoo.Bar();và bạn nhận được khiếu nại rằng "công khai" và "trừu tượng" không phải là công cụ sửa đổi hợp lệ.
Darren Cook

8
Điều này không trả lời câu hỏi tại sao điều này thậm chí còn cần thiết, vì đây là một lớp trừu tượng và trình biên dịch nên biết cách điền vào chỗ trống. Trong Java, điều này là không cần thiết, cho phép một số mẫu hữu ích như mẫu trang trí trên các thùng chứa ioc, ví dụ Spring / JavaEE (khi bạn cần trang trí một phương thức cụ thể của giao diện được quản lý). Việc triển khai tương tự in.net sẽ buộc các nhà phát triển phải rất dài dòng, đặc biệt là trên các giao diện lớn như ISession của nhibernate
Sheepy

1
Mixins của AspectJ là một ví dụ khác. Nó cho phép bạn kết hợp các triển khai một phần từ nhiều lớp trừu tượng vào một giao diện duy nhất. Mỗi lớp trừu tượng chỉ cần thực hiện phương thức mà nó muốn thực hiện. Không có bản tóm tắt phương pháp trừu tượng ngu ngốc nào cản trở như trường hợp nếu tôi tạo lại chức năng tương tự trong .net
Sheepy

1
@Sheepy - Đúng, nhưng, IMHO, bạn hiểu sai những gì người hỏi cần , và đây thực sự là một "câu trả lời" như thế nào. Tôi cũng có câu hỏi tương tự - bởi vì nó không có nghĩa là bắt buộc phải cung cấp một triển khai, vì vậy tôi đã bị mắc kẹt. Câu trả lời là: Bạn không phải " thực hiện " nó - nhưng đây là những gì bạn phải làm để nói với trình biên dịch rằng bạn sẽ không thực hiện nó. (Câu hỏi mà bạn [chính xác] nói rằng đây không phải là câu trả lời, sẽ không phải là một câu hỏi stackoverflow thích hợp - nó chỉ đơn giản là bị đóng vì mục đích không phù hợp.)
ToolmakerSteve

10

Không giống như Java, trong C #: "một lớp trừu tượng phải cung cấp các triển khai của tất cả các thành viên của các giao diện được liệt kê trong danh sách lớp cơ sở của lớp. Tuy nhiên, một lớp trừu tượng được phép ánh xạ các phương thức giao diện lên các phương thức trừu tượng."

https://msdn.microsoft.com/en-us/l Library / Aa664595 (v = VS.71) .aspx


1
Câu trả lời siêu rõ ràng và tuyệt vời khi bạn cung cấp cả hai tình huống, vì đôi khi bạn cũng có thể muốn thực hiện hành vi trong lớp cơ sở
VinKel

Một câu hỏi được đặt ra ở đây là: tại sao các khai báo soạn sẵn C # này (rõ ràng là chúng) cần tồn tại trong các lớp trừu tượng, có thể ngắn gọn và ngắn gọn hơn (do đó làm rối các lớp)? Trong dự án C # của tôi, tôi có rất nhiều lớp và giao diện trừu tượng - và những gì tôi làm trong hầu hết thời gian là sao chép và dán các khai báo phương thức trong Visual Studio.
forsberg

5

Họ không phải thực sự thực hiện giao diện .
Các phương thức / thuộc tính giao diện có thể là trừu tượng hoặc thậm chí là ảo. Vì vậy, nó lên đến các lớp con để thực sự thực hiện chúng.

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.