2011-08-24 28 views

Trả lời

14

Không, bạn có thể ẩn thành viên công cộng với một phương pháp tư nhân trong một lớp con, nhưng bạn có thể không override thành viên công cộng với một tư nhân trong một lớp con. Và, trên thực tế, nó không chỉ là một điều công cộng/riêng tư, điều này áp dụng cho việc thu hẹp quyền truy cập nói chung.

Revised: Bằng cách ẩn với một truy cập hạn chế hơn - trong trường hợp này truy cập tin - bạn sẽ vẫn thấy các thành viên lớp cơ sở từ một cơ sở đẳng cấp hoặc tham chiếu sub-class, nhưng nó sẽ hoãn đến mới khi có sẵn từ cấp truy cập mới.

Vì vậy, nói chung, khi bạn ẩn, ẩn sẽ được ưu tiên khi hiển thị ở cấp truy cập. Nếu không, phương pháp ban đầu là phương pháp được sử dụng.

public class BaseClass 
{ 
    public virtual void A() { } 

    public virtual void B() { } 
} 

public class SubClass 
{ 
    // COMPILER ERROR, can't override to be more restrictive access 
    private override void A() { } 

    // LEGAL, you can HIDE the base class method, but which is chosen 
    // depends on level accessed from 
    private new void B() { } 
} 

Vì vậy, SubClass.B() CHỈ ẩn các phương thức lớp cơ sở khi có thể truy cập. Tức là, nếu bạn gọi SubClass.B() bên trong của SubClass thì nó sẽ có dạng ẩn là B(), nhưng vì B() là riêng tư, không hiển thị với các lớp bên ngoài chính nó và do đó chúng STILL thấy BaseClass.B().

Các dài và ngắn của nó là:

1) Bạn không có thể ghi đè một phương pháp để có hạn chế hơn (truy cập khôn ngoan). 2) Bạn có thể ẩn một phương thức với một phương thức hạn chế hơn, nhưng nó sẽ chỉ có tác dụng khi loại truy cập mới hiển thị, nếu không thì kiểu cơ sở sẽ hiển thị.

public class BaseClass 
{ 
    public virtual void A() { } 
    public virtual void B() { } 
} 

public class SubClass : BaseClass 
{ 
    public virtual void A() { B(); } 

    // legal, you can do this and B() is now hidden internally in SubClass, 
    // but to outside world BaseClass's B() is still the one used. 
    private new void B() { } 
} 

// ... 

SubClass sc = new SubClass(); 
BaseClass bc = new BaseClass(); 

// both of these call BaseClass.B() because we are outside of class and can't 
// see the hide SubClass.B(). 
sc.B(); 
bc.B(); 

// this calls SubClass.A(), which WILL call SubClass.B() because the hide 
// SubClass.B() is visible within SubClass, and thus the hide hides BaseClass.B() 
// for any calls inside of SubClass. 
sc.A(); 
+0

Bạn có chắc chắn về điều đó không? Có vẻ như nó sẽ phá vỡ của Liskov –

+0

Bạn có thể làm điều đó. Tuy nhiên, bạn chỉ có thể truyền nó vào 'BaseClass' và gọi phương thức như thể không có gì xảy ra. – Femaref

+0

@Brian: Đúng, ẩn để hạn chế hơn được cho phép. Biên dịch tốt.Hãy nhớ rằng phương thức vẫn tồn tại, và miễn là bạn coi nó như là một tham chiếu lớp cơ sở, nó vẫn ở đó và chạy, nó không thể nhìn thấy từ một lớp con (trong trường hợp ẩn riêng). Không nói nó luôn là sự lựa chọn tốt nhất, OO khôn ngoan, nhưng nó có thể trong C#. –

3

Không.

Cách điển hình để giải quyết vấn đề này là ném NotImplementedException hoặc thứ gì đó vào hiệu ứng đó.

+6

'NotImplementedException' ngụ ý một cái gì đó bị bỏ qua do nhầm lẫn. 'NotSupportedException' ngụ ý một cái gì đó bị bỏ qua bởi thiết kế (và có thể * vẫn * do nhầm lẫn, như trường hợp có thể). –

2

Bạn không thể thu hẹp hoặc mở rộng khả năng hiển thị của thành viên bị ghi đè. Tuy nhiên, bạn có thể xác định phương thức khác bằng từ khóa new, có thể cung cấp cho bạn phương thức mới với cùng tên , nhưng không tương thích về mặt đa hình.

public class A : B 
{ 
    public new void Foo() 
    { 
     base.Foo(); 
    } 
} 
+2

Đó không phải là quá ** chuyến đi **, đó là quá ** viết **. Nếu bạn bỏ lớp này sang 'B', phương thức sẽ có sẵn, ngay cả khi bạn ghi đè nó trong' A'. – Femaref

+0

@Femaref Về mặt kỹ thuật, loại quyền tốt nhất. –

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