2010-03-23 42 views
15

Tôi đang học C# và tôi gặp sự cố sau. Tôi có hai lớp: cơ sở và nguồn gốc:C# Ẩn, ghi đè và gọi hàm từ lớp cơ sở

class MyBase 
{ 
    public void MyMethod() 
    { 
     Console.WriteLine("MyBase::MyMethod()"); 
    } 
} 


class MyDerived: MyBase 
{ 
    public void MyMethod() 
    { 
     Console.WriteLine("MyDerived::MyMethod()"); 
    } 
} 

Còn bây giờ, mà không virtualoverride từ khóa. Khi tôi biên dịch, tôi nhận được cảnh báo (dĩ nhiên là dự kiến) mà tôi cố gắng ẩn MyMethod từ lớp MyBase.

Điều tôi muốn làm là gọi phương thức từ lớp cơ sở có thể hiện của lớp dẫn xuất. Tôi làm như sau:

MyDerived myDerived = new MyDerived(); 
((MyBase)myDerived).MyMethod(); 

Nó hoạt động tốt khi tôi không chỉ định bất kỳ virtual, v.v ... từ khóa trong phương pháp. Tôi đã cố gắng kết hợp các từ khóa và tôi nhận được các kết quả sau:

| MyBase::MyMethod | MyDerived::MyMethod | Result printed on the console | 
| -----------------|---------------------|-------------------------------| 
| -    | -     | MyBase::MyMethod()   | 
| -    | new     | MyBase::MyMethod()   | 
| virtual   | new     | MyBase::MyMethod()   | 
| virtual   | override   | MyDerived::MyMethod()   | 

Tôi hy vọng bảng này rõ ràng cho bạn. Tôi có hai câu hỏi:

  1. Đó có phải là cách chính xác để gọi hàm từ lớp cơ sở (((MyBase)myDerived).MyMethod();)? Tôi biết về base từ khóa, nhưng nó có thể được gọi chỉ từ bên trong của lớp dẫn xuất. Đúng không?
  2. Tại sao trong trường hợp cuối cùng (với virtualoverride công cụ sửa đổi) phương thức được gọi đến từ lớp dẫn xuất? Bạn vui lòng giải thích điều đó không?
+0

Bạn có thể vui lòng giải thích về những gì bạn muốn * chứ không phải những gì bạn đã trải nghiệm? Tất cả những gì tôi có thể nói ngay bây giờ là "Có, có vẻ đúng". Đối với câu hỏi cuối cùng, bạn thực sự nên đọc về cách thức hoạt động của phương thức ảo. Xem http://en.wikipedia.org/wiki/Virtual_method_table để biết thông tin. –

Trả lời

18

Khi bạn gọi phương thức virtual trên cá thể loại ghi đè phương pháp, phiên bản ghi đè sẽ luôn được gọi, ngay cả khi bạn chuyển sang lớp cơ sở.

Cách duy nhất để gọi triển khai cơ sở của phương thức ảo trên lớp ghi đè phương thức là tạo phương thức thứ hai trong lớp dẫn xuất (không phải lớp cơ sở) gọi phương thức sử dụng từ khóa base.

Nói chung, cần phải làm điều này là một dấu hiệu của một thiết kế API kém - nếu bạn nghĩ rằng bạn sẽ cần phải gọi phiên bản cơ sở, phiên bản có nguồn gốc nên có thể có một tên khác.

+2

+1 - được giải thích rõ ràng. Thêm điểm cho thảo luận thiết kế. –

2

Bạn chính xác - base chỉ có thể được gọi từ bên trong lớp dẫn xuất - Source.

Trang này cũng cung cấp ví dụ về cách ghi đè định nghĩa lớp cơ sở.

3

Đối với câu hỏi thứ hai của bạn, bạn không thay đổi loại đối tượng mà bạn tham chiếu, chỉ là giao diện mà bạn đang tham chiếu. Vì vậy, nếu bạn có đối tượng B kế thừa từ A và ghi đè hàm C, ngay cả khi bạn tham chiếu đến B dưới dạng A, nó vẫn gọi là triển khai loại có nguồn gốc cao nhất, trong trường hợp này B.

2
  1. Bạn ' bên phải, base dùng để chỉ lớp cơ sở cho một trường hợp cụ thể.
  2. Cơ chế liên quan được gọi là đa hình: bạn nên làm việc tốt hơn mà không cần cảnh báo. Các đối tượng tự nhiên theo định hướng tốt là cách cuối cùng của các trường hợp bạn đã đề cập.

Nhân tiện, cố gắng tránh viết mã thực thi nguyên tắc thay thế, nói cách khác, không viết mã phụ thuộc vào việc triển khai phân cấp lớp của bạn vì bạn sẽ phải sửa đổi mã này nếu bạn thêm một lớp dẫn xuất mới vào lớp cơ sở của bạn.

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