C#學習筆記:多態與隱藏,覆蓋

來源:互聯網
上載者:User

以繼承為基礎,繼承舉例:

public class Person
{
 public void Sayhello()
 {
  Console.WriteLine("Hello,I am a person");
 }
}
public class Student:Person
{
}

 

Student類繼承與Person類

我們想改變Student裡面繼承Person的SayHello()方法,使其具有自己的特性.這裡使用new關鍵字.

public class Person
{
 public void SayHello()
 {
  Console.WriteLine("Hello,I am a person");
 }
}
public class Student:Person
{
 new public void SayHello()
 {
  Console.WriteLine("hello,I am a student");
 }
}

public class Test
{
 static void Main()
 {
  Person aPerson=new Person();
  Student aStudent = new aStudent();
  
  aPerson.SayHello();
  aStudent.SayHello();
 }
}

輸出:
hello,I am a person
hello,I am a student

這個過程在Inside C#-MSPress稱為override:
you want to derive a class from (Person) and you want to override the (SayHello) method to do something specific to the derived class. To do this, you need to use the new keyword with the derived class's method definition.
但在翻譯成中文時,稱為:隱藏.

多態(Polymorphism)

當使用關鍵字new來override基類的方法時,程式運行很盡人意.
(Method overriding with the new keyword works fine if you have a reference to the derived object)

語言的每個概念的產生都是需要理由的(你不防問問自己為什麼c#會有Class,Method...這些概念),這裡,我們要問:
為什麼會有多態這個概念的出現?有什麼用處呢?
(看了很多.NET書籍,好像沒有這樣來解釋各個概念的)

從實際出發,看下面例子:Student,Teacher都是Person,在實際應用中,我們需要把所有Person的衍生類別組裝(populate)到一個數組裡面,這個數組的資料類型必定是Person了,而且,通過這個Person[]數組來重新調用數組元素(Person的衍生類別)的SayHello方法.

public class Person
{
 public void SayHello()
 {
  Console.WriteLine("Hello,I am a person");
 }
}
public class Student:Person
{
 new public void SayHello()
 {
  Console.WriteLine("hello,I am a student");
 }
}
public class Teacher:Person
{
 new public void SayHello()
 {
  Console.WriteLine("hello,I am a teacher");
 }
}
public class Test
{
 private static Person[] persons=new Person[2];
 static void Main()
 {
  persons[0]=new Student();
  persons[1]=new Teacher();
 
  persons[0].SayHello();
  persons[1].SayHello();
 }
}

輸入結果:
hello,I am a person
hello,I am a person

(Obviously, this is not what we wanted)對,在實際應用中,我們不希望出現這種結果.
希望輸出:
hello,I am a student
hello,I am a teacher

上面的例子,為什麼會出現我們所不希望的結果呢?
看看Inside C#的解釋:

What happened here is an example of a phenomenon called early binding. When the code was compiled, the C# compiler looked at the call to Persons[].SayHello() and determined the address in memory that it would need to jump to when the call is made. In this case, that would be the memory location of the Person.SayHello method.
Take a look at the following MSIL that was generated from the Test application, and specifically take note of line IL_0014 and the fact that it explicitly calls the Employee.CalculatePay method:

....
IL_0014:  call       instance void Employee::CalculatePay()

....

That call to the (Person.SayHello) method is the problem. What we want instead is for late binding to occur. Late binding means that the compiler does not select the method to execute until run time. To force the compiler to call the correct version of an upcasted object's method, we use two new keywords: virtual and override. The virtual keyword must be used on the base class's method, and the override keyword is used on the derived class's implementation of the method.

public class Person
{
 virtual public void SayHello()
 {
  Console.WriteLine("Hello,I am a person");
 }
}
public class Student:Person
{
 override public void SayHello()
 {
  Console.WriteLine("hello,I am a student");
 }
}
public class Teacher:Person
{
 override public void SayHello()
 {
  Console.WriteLine("hello,I am a teacher");
 }
}
public class Test
{
 private static Person[] persons=new Person[2];
 static void Main()
 {
  persons[0]=new Student();
  persons[1]=new Teacher();
 
  persons[0].SayHello();
  persons[1].SayHello();
 }
}

Before running this application, let's take a peek at the IL code that's generated, this time noting that line IL_0014 uses the MSIL opcode callvirt,which tells the compiler that the exact method to be called won't be known until run time because it's dependent on which derived object is being used:

.....
IL_0014:  callvirt   instance void Employee::CalculatePay()
.....

輸出為:
hello,I am a student
hello,I am a teacher

要深刻理解這個過程,必須搞明白什麼是"Early Binding&Late Binding","run time",具有"編譯原理"相關知識.
本人還沒有學習"編譯原理"以及"組譯工具",這一點還是沒有搞徹底,不再引用這方面的資料,可以查閱MSDN

BTW,我們還可以用類型轉換來得到我們想要的:
class Test修改為:

public class Test
{
 private static Person[] persons=new Person[2];
 static void Main()
 {
  persons[0]=new Student();
  persons[1]=new Teacher();
 
  Student s=new Student();
  Teacher t=new Teacher();

  s=(Student)persons[0];
  t=(Teacher)Persons[1];

  s.SayHello();
  t.SayHello();

 }
}

===========================================
以上文章參考(部分字句為直接翻譯)
[1]Inside C# / Tom Archer.(Microsoft Press)
[2]Visual C# .NET:A Gudie for VB6 Develops/Brand Maiani,James Still...(Wrax)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.