Câu trả lời:
Kế thừa tốt ...
giả sử bạn có các lớp này:
class A {
public int Foo(){ return 5;}
public virtual int Bar(){return 5;}
}
class B : A{
public new int Foo() { return 1;} //shadow
public override int Bar() {return 1;} //override
}
thì khi bạn gọi cái này:
A clA = new A();
B clB = new B();
Console.WriteLine(clA.Foo()); // output 5
Console.WriteLine(clA.Bar()); // output 5
Console.WriteLine(clB.Foo()); // output 1
Console.WriteLine(clB.Bar()); // output 1
//now let's cast B to an A class
Console.WriteLine(((A)clB).Foo()); // output 5 <<<-- shadow
Console.WriteLine(((A)clB).Bar()); // output 1
Giả sử bạn có một lớp cơ sở và bạn sử dụng lớp cơ sở trong tất cả mã của mình thay vì các lớp kế thừa và bạn sử dụng bóng, nó sẽ trả về các giá trị mà lớp cơ sở trả về thay vì theo sau cây kế thừa kiểu thực của đối tượng.
Hy vọng tôi có ý nghĩa :)
Shadowing thực sự là cách nói của VB cho những gì chúng ta muốn gọi là ẩn trong C #.
Thường ẩn (bóng trong VB) và ghi đè được hiển thị như trong câu trả lời của Stormenet .
Một phương thức ảo được chỉ ra là được ghi đè bởi lớp con và các cuộc gọi đến phương thức đó ngay cả trên kiểu siêu lớp hoặc từ mã bên trong của lớp siêu sẽ gọi việc thực thi thay thế từ lớp con.
Sau đó, một phương thức cụ thể được hiển thị (một phương thức không được đánh dấu là ảo hoặc trừu tượng) đang bị ẩn bằng cách sử dụng new
từ khóa khi định nghĩa một phương thức có chữ ký giống hệt nhau trên lớp con. Trong trường hợp này khi phương thức được gọi trên kiểu siêu lớp, việc triển khai ban đầu được sử dụng, việc triển khai mới chỉ khả dụng trên lớp con.
Tuy nhiên điều thường bị bỏ sót là nó cũng có thể ẩn một phương pháp ảo.
class A
{
public virtual void DoStuff() { // original implementation }
}
class B : A
{
public new void DoStuff() { //new implementation }
}
B b = new B();
A a = b;
b.DoStuff(); //calls new implementation
a.DoStuff(); //calls original implementation.
Lưu ý trong ví dụ trên DoStuff trở nên cụ thể và không thể bị ghi đè. Tuy nhiên, cũng có thể sử dụng cả từ khóa virtual
và new
từ khóa cùng nhau.
class A
{
public virtual void DoStuff() { // original implementation }
}
class B : A
{
public new virtual void DoStuff() { //new implementation }
}
class C : B
{
public override void DoStuff() { //replacement implementation }
}
C c = new C();
B b = c;
A a = b;
c.DoStuff(); //calls replacement implementation
b.DoStuff(); //calls replacement implementation
a.DoStuff(); //calls original implementation.
Lưu ý rằng mặc dù tất cả các phương thức liên quan là ảo, việc ghi đè lên C không ảnh hưởng đến phương thức ảo trên A vì việc sử dụng new
trong B ẩn việc triển khai A.
Biên tập: Nó đã được lưu ý trong các nhận xét cho câu trả lời này rằng những điều trên có thể nguy hiểm hoặc ít nhất là không đặc biệt hữu ích. Tôi sẽ nói có nó có thể nguy hiểm và sẽ ra khỏi đó nếu nó có ích.
Đặc biệt, bạn có thể gặp đủ loại rắc rối nếu bạn cũng thay đổi công cụ sửa đổi khả năng truy cập. Ví dụ:-
public class Foo
{
internal Foo() { }
protected virtual string Thing() { return "foo"; }
}
public class Bar : Foo
{
internal new string Thing() { return "bar"; }
}
Đối với người kế thừa bên ngoài Bar
, Foo
việc triển khai Thing () vẫn có thể truy cập và có thể ghi đè. Tất cả hợp pháp và có thể giải thích được theo quy tắc loại .NET không bao giờ ngoại trừ khá khó hiểu.
Tôi đã đăng câu trả lời này để hiểu sâu hơn về cách mọi thứ hoạt động không phải là gợi ý về các kỹ thuật có thể được sử dụng tự do.
Tôi nghĩ sự khác biệt chính là với đổ bóng, về cơ bản bạn đang sử dụng lại tên và chỉ bỏ qua việc sử dụng lớp cha. Với ghi đè, bạn đang thay đổi việc triển khai, nhưng không thay đổi khả năng truy cập và chữ ký (ví dụ: kiểu tham số và trả về). Xem http://www.geekinterview.com/question_details/19331 .
Shadowing là một khái niệm VB.NET. Trong C #, Shadowing được gọi là Ẩn. Nó ẩn phương thức lớp dẫn xuất. Nó được hoàn thành bằng cách sử dụng từ khóa 'mới'.
Từ khóa ghi đè được sử dụng để cung cấp một triển khai hoàn toàn mới của một phương thức lớp cơ sở (được đánh dấu là 'Ảo') trong lớp dẫn xuất.
Về cơ bản, nếu bạn có một cái gì đó như bên dưới,
Class A
{
}
Class B:A
{
}
A a = new B();
Bất kỳ phương thức nào bạn gọi trên đối tượng 'a' sẽ được thực hiện theo kiểu 'a' (Ở đây kiểu là 'A') Nhưng nếu bạn triển khai cùng một phương thức trong lớp B đã có trong Lớp A, trình biên dịch sẽ cung cấp cho bạn một cảnh báo để sử dụng từ khóa "Mới". Nếu bạn sử dụng "Mới", cảnh báo sẽ biến mất. Ngoài điều này, không có sự khác biệt giữa việc sử dụng "Mới" hoặc không sử dụng nó trong lớp kế thừa.
Trong một số trường hợp, bạn có thể cần gọi một phương thức của lớp tham chiếu mà cá thể cụ thể đang giữ tại thời điểm đó thay vì gọi một phương thức trên kiểu đối tượng. Trong trường hợp trên, tham chiếu mà nó giữ là 'B', nhưng kiểu là 'A'. Vì vậy, nếu bạn muốn cuộc gọi phương thức xảy ra trên 'B', thì bạn sử dụng Virtual và ghi đè để đạt được điều này.
Hi vọng điêu nay co ich...
Daniel Sandeep.
Nếu có trường hợp bạn không thể thay đổi nội dung của một lớp, giả sử A
, nhưng bạn muốn sử dụng một số phương thức của nó cùng với việc bạn có một phương thức có tên phổ biến, bạn có thể sử dụng triển khai phương thức của riêng mình bằng cáchnew
từ khóa.
Điểm mấu chốt là sử dụng nó rằng cả tham chiếu và đối tượng phải cùng loại.
class A
{
public void Test()
{
Console.WriteLine("base");
}
}
class B : A
{
public new void Test()
{
Console.WriteLine("sub");
}
public static void Main(string[] args)
{
A a = new A();
B aa = new B();
a.Test();
aa.Test();
}
}