2013-07-16 34 views
6

tôi đang cố gắng hiểu sự cần thiết của override và ảo trong C#, vì vậy tôi đã viết đoạn mã sau:Nếu lớp dẫn xuất không ghi đè lên phương thức, phiên bản nào sẽ được gọi?

using System; 
namespace Override 
{ 
    class Base 
    { 
     public virtual void method() 
     { 
      Console.WriteLine("Base method"); 
     } 
    } 
    class Derived : Base 
    { 
     public override void method() 
     { 
      Console.WriteLine("Derived method"); 
     } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Derived d = new Derived(); 
      d.method(); 
     } 
    } 
} 

Và tôi đã mong đợi "phương pháp nguồn gốc" để được gọi và printed.Then tôi đã viết đoạn code sau đây mà không bằng cách sử dụng kết hợp ảo/ghi đè.

using System; 
namespace Override 
{ 
    class Base 
    { 
     public void method() 
     { 
      Console.WriteLine("Base method"); 
     } 
    } 
    class Derived : Base 
    { 
     public void method() 
     { 
      Console.WriteLine("Derived method"); 
     } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Derived d = new Derived(); 
      d.method(); 
     } 
    } 
} 

Và tôi nhận được cùng một kết quả tức là "Mã nguồn gốc" được gọi và in. Câu hỏi của tôi là nếu mã hoạt động mà không có ảo/ghi đè như tôi mong đợi, chúng cần gì? hoặc tôi đang thiếu một cái gì đó ở đây?

+0

Bạn không nhận được cảnh báo trong phương pháp thứ hai về việc ẩn phương pháp? "'Derived.Method()' ẩn thành viên kế thừa Base.Method() '. Sử dụng từ khóa mới nếu ẩn được dự định. \t" – Sayse

+0

Cảm ơn tất cả các câu trả lời, bây giờ tôi rõ ràng với khái niệm này – ZoomIn

Trả lời

11

Trong mã nguồn, bạn luôn thực hiện kế thừa đơn giản mà không có bất kỳ hành vi đa hình nào. Bạn luôn tạo ra thể hiện của lớp dẫn xuất và gán nó cho biến cá thể lớp dẫn xuất.

DerivedClass d = new DerivedClass(); // here no polymorphism, and only inheritance is there 

Vì vậy, khi bạn gọi phương thức sử dụng biến lớp, phương thức này sẽ luôn gọi phương thức DerivedClass, cho dù phương thức là ảo hay không trong lớp cha.

Trong đa hình, chương trình của bạn không biết loại chính xác của lớp mà bạn đang gọi phương thức (khái niệm này được gọi là kết thúc muộn). Như ví dụ bên dưới:

BaseClass b = new DerivedClass(); // here b is a base class instance but initiated using derived class 

Sau khi gọi b.phương thức() nó sẽ thực hiện ràng buộc trễ và sẽ hiển thị hành vi đa hình (chỉ khi phương thức đã được đặt ảo trong lớp cơ sở)

LƯU Ý: Từ khóa ảo trì hoãn ràng buộc đúng phiên bản của phương thức để chạy và là lõi keywork để thực hiện đa hình. Vì vậy, đối với hành vi đa hình chính xác, khai báo các phương thức như ảo trong lớp cha, và sau đó trong lớp con, ovverride phương thức đó.

+0

Cảm ơn - từ khóa cho tôi ở đây là "sự ràng buộc chậm trễ". – Eccountable

8

virtual cho phép phiên bản chính xác của phương thức được chọn trong thời gian chạy, dựa trên thông tin không có sẵn tại thời gian biên dịch. Hãy xem xét các tinh chỉnh sau để dụ của bạn:

using System; 
namespace Override 
{ 
    class Base 
    { 
     public virtual void method() 
     { 
      Console.WriteLine("Base method"); 
     } 
    } 
    class Derived : Base 
    { 
     public override void method() 
     { 
      Console.WriteLine("Derived method"); 
     } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Derived d = new Derived(); 
      Base b = d; 
      b.method(); 
     } 
    } 
} 

Với virtual/override, mã này sẽ hiển thị Derived method, như khi chạy chúng ta có thể thấy rằng b thực sự là một trường hợp Derived. Nếu không có virtual/override, nó sẽ hiển thị Base method, như loại được khai báo là bBase.

0

Phương thức 'phương pháp' trên lớp Có nguồn gốc sẽ ẩn việc triển khai lớp Cơ sở, đó là lý do bạn nhận được "Phương thức có nguồn gốc" được lưu trữ.

Có nhiều cách sử dụng ảo và trừu tượng nhưng một ví dụ là nơi bạn có chức năng trong lớp cơ sở có thể không phù hợp với tất cả các trường hợp lớp kế thừa từ lớp cơ sở của bạn. Sử dụng ảo cho phép một lớp khác hoàn toàn ghi đè lên chức năng đó và cung cấp việc thực hiện riêng của nó.

3

Đây là bài kiểm tra bạn đang thiếu:

Base d = new Derived(); 
d.method(); // "Derived method" 

Base b = new Base(); 
b.method(); // "Base method" 

Cũng hãy tưởng tượng nếu bạn đã có một bộ sưu tập các Base đối tượng đã được sáng tác của các đối tượng di truyền khác nhau. Từ khóa virtual cho phép các đối tượng Base hiểu loại thực sự của chúng khi chạy.

List<Base> collection = new List<Base>(); 
collection.Add(new Base()); 
collection.Add(new Derived()}; 
collection.Add(new Base()); 

foreach(Base b in collection) 
{ 
    b.method(); // will print out "Base" or "Derived" correctly 
} 
2

thấy sự khác biệt

 class Base 
     { 
      public void method() 
      { 
       Console.WriteLine("Base method"); 
      } 
     } 
     class Derived : Base 
     { 
      public void method() 
      { 
       Console.WriteLine("Derived method"); 
      } 
     } 
     class Program 
     { 
      static void Main(string[] args) 
      { 
       Derived d; 

       d = new Derived(); 
       d.method(); 

       d = new Base(); 
       d.method(); 
      } 
     } 

OUTPUT:
phương pháp nguồn gốc
phương pháp nguồn gốc

  class Base 
      { 
       public virtual void method() 
       { 
        Console.WriteLine("Base method"); 
       } 
      } 
      class Derived : Base 
      { 
       public override void method() 
       { 
        Console.WriteLine("Derived method"); 
       } 
      } 
      class Program 
      { 
       static void Main(string[] args) 
       { 
        Derived d; 

        d = new Derived(); 
        d.method(); 

        d = new Base(); 
        d.method(); 
       } 
      } 

OUTPUT:
phương pháp nguồn gốc
phương pháp cơ sở

+1

Điều đó thậm chí sẽ không biên dịch, không thể đặt d thành Cơ sở mới() .. Ví dụ của bạn đang cố gắng làm giống như Chowletts cũng trả lời – Sayse

2

con trỏ lớp cơ sở có thể được sử dụng để trỏ đến đối tượng của lớp cơ sở hoặc bất kỳ đối tượng có nguồn gốc từ cơ sở. Vì vậy, nhu cầu của các phương pháp ảo đi vào hình ảnh khi đối tượng lớp cơ sở trỏ đến lớp dẫn xuất

Base d = new Derived(); 
d.method(); // "Derived method" 
Các vấn đề liên quan