2010-05-06 22 views
22

Có cách nào để lớp học 'loại bỏ' các phương thức mà nó đã được kế thừa không?Có cách nào để một lớp học 'loại bỏ' phương pháp mà nó đã được thừa kế?

Ví dụ: nếu tôi không muốn lớp học của mình có phương thức ToString() thì tôi có thể làm gì đó để nó không còn khả dụng không?

+2

http://www.codinghorror.com/blog/2004/08/inherits-nothing.html – Svisstack

+1

này được gọi là "từ chối Bequest" mã mùi: "một lớp ghi đè một phương thức của một lớp cơ sở theo cách mà hợp đồng của lớp cơ sở không được vinh danh bởi lớp dẫn xuất ". http://en.wikipedia.org/wiki/Code_smell – Mathias

+0

Không có cách nào để xóa phương thức. Nếu phương thức là 'virtual' (được đánh dấu bằng' virtual', 'abstract' hoặc' override'), bạn may mắn vì tác giả của lớp cơ sở cho phép bạn quyết định hành vi của phương thức. Bạn có thể làm cho nó không làm gì, hoặc ném một ngoại lệ (nhưng lưu ý rằng điều này có thể phá vỡ sự mong đợi của lớp cơ sở từ phương thức của bạn, vì vậy nó sẽ giới thiệu các vấn đề trong các trường hợp _some_). Nếu phương pháp này không phải là ảo, bạn không thể làm được gì nhiều. Ẩn nó với một phương pháp khác là một ý tưởng rất xấu (và không loại bỏ nó tất nhiên). –

Trả lời

28

Không - điều này sẽ vi phạm Liskov's Substitution Principle. Bạn nên luôn có thể sử dụng một thể hiện của một kiểu con như thể nó là một thể hiện của một siêu kiểu.

Đừng quên rằng người gọi chỉ có thể biết loại của bạn "là" loại cơ sở hoặc giao diện. Hãy xem xét mã này:

object foo = new TypeWithToStringRemoved(); 
foo.ToString(); 

Điều đó sẽ phải biên dịch, phải không? Bây giờ bạn mong đợi điều gì sẽ xảy ra vào thời gian thực hiện?

Bây giờ cho ToString, GetHashCode, EqualsGetType không có cách nào để tránh việc họ ở nơi đầu tiên - nhưng thường nếu có những phương pháp bạn muốn "loại bỏ" từ một loại cơ sở, gợi ý rằng bạn không nên kế thừa từ nó ở nơi đầu tiên. Cá nhân tôi tìm thấy vai trò của thừa kế được phần nào overplayed trong lập trình hướng đối tượng: nơi nó hữu ích là thực sự hữu ích, nhưng nói chung tôi thích thành phần hơn thừa kế, và giao diện như là một hình thức trừu tượng hơn là lớp cơ sở.

+1

Bạn hoàn toàn đúng - nó đặc biệt nguy hiểm để làm cho phương thức 'ToString()' ném một ngoại lệ. Có rất nhiều * ẩn * tập quán của 'ToString()' hơn một trong những bạn đã cho thấy (gọi nó trực tiếp). – tanascius

+0

Nhưng chắc chắn bạn có thể sử dụng công cụ sửa đổi 'mới' để ẩn một thành viên được thừa kế (và ném một NotSupportedException, như đề xuất tanascius), mà không vi phạm bất kỳ nguyên tắc nào hoặc ném các ngoại lệ không mong muốn. –

+0

@ Allon: Nó sẽ luôn luôn bất ngờ, khi một cuộc gọi 'ToString()' ném một ngoại lệ ... – tanascius

15

Bạn có thể ném một NotSupportedException, đánh dấu nó như Obsolete và sử dụng EditorBrowsable:

[EditorBrowsable(EditorBrowsableState.Never)] 
[Obsolete("...", false)] 
void YourMethod() 
{ 
    throw new NotSupportedException("..."); 
} 

EDIT:
Như đã chỉ ra bởi những người khác: Tôi mô tả một cách để "vô hiệu hóa" phương pháp, nhưng bạn phải suy nghĩ cẩn thận, nơi bạn muốn sử dụng nó. Đặc biệt là ném ngoại lệ có thể là một điều rất nguy hiểm.

+0

@tanascius: Nếu bạn nhận được sự phân biệt ngoại lệ từ tài sản lỗi thời, mã của bạn sẽ tốt ;-) – Svisstack

+0

@Svisstack: Không, đó là hai chuỗi khác nhau ^^ Có lẽ chúng sẽ khác nhau, vì thông điệp * lỗi thời dành cho nhà phát triển, trong khi thông báo * ngoại lệ * có thể tiếp cận người dùng? Vâng, có lẽ không - ít nhất là nó không nên. – tanascius

+0

ok, bạn bảo vệ ;-) – Svisstack

1

Awnser ngắn, KHÔNG như tất cả các lớp kế thừa từ đối tượng và đối tượng có phương pháp này.

4

Như những người khác đã chỉ ra, bạn không thể "loại bỏ" một phương pháp, nhưng nếu bạn cảm thấy nó đã làm bạn bị sai theo một cách nào đó bạn có thể hide it (trong lớp học của bạn).

Từ tài liệu:

class Base 
{ 
    public static void F() {} 
} 
class Derived: Base 
{ 
    new private static void F() {} // Hides Base.F in Derived only 
} 
class MoreDerived: Derived 
{ 
    static void G() { F(); }   // Invokes Base.F 
} 
+0

F phải được bảo vệ phải không? –

+0

@ChristopheDebove Ví dụ đó là trực tiếp từ MSDN, vì vậy tôi cho rằng chúng có nghĩa là cho nó là riêng tư. – R0MANARMY

Các vấn đề liên quan