簡介
多態性是面向對象的三大特徵之一,個人的多態性往往是指,同一個方法在不同的代碼環境下表現出來的不同功能,典型的用法就是在抽象類和接口中的使用。多態性,就是多種形態的形式,通常分爲兩種,靜態的和動態的多態性。在靜態多態性中,就是指函數或者方法在編譯期間就發生的多種形態展示,典型的就是方法重載或者運算符重載;在動態多態性中,就是指函數或者方法在運行期間發生的多種形態方式,通常就是我們常見的類繼承中抽象方法揮着虛方法重寫;或者可以從另外一種角度進行分類,根據多態發生的作用域,可以將分爲單類內部的多態性體現和繼承類和父類之間的多態性體現。
編譯多態性
在編譯期間就可以實現多態性,也成爲靜態多態性。在C#中典型的有兩種方式實現:
函數重載
運算符重載
函數重載,通常用於在同一作用域對相同的函數有多個定義,多種實現。但是定義之間必須存在編譯器可識別的差異,就是函數簽名必須不同,通常有三個要求:方法名稱必須一致、參數列表必須不同、返回值隨意。下面舉一個例子:
using System;
namespace TestForPolymorphism
{
class Test
{
static void Main(string[] args)
{
Book book1= new Book(){BookName = "鋼鐵是怎樣煉成的",BookID = "1",BookValue =45 };
Student student1 = new Student(){StudentName = "小王",StudentID = "20181215001"}
Library library1 = new Library();
library1.LoadBook(book1);
library1.LoadBook("鋼鐵是怎樣煉成的","1",45,"");
Console.ReadKey();
}
}
public class Library
{
public Library(){}
private List<Book> booklist;
public List<Book> Booklist{get;set;}
private List<Student> studentlist;
public List<Student> Studentlist{get;set;}
private List<BorrowRecord> borrowlist;
public List<BorrowRecord> Borrowlist{get;set;}
private List<ReturnRecord> returnlist;
public List<ReturnRecord> Returnlist{get;set;}
public void LoadBook(Book bookitem)
{
Console.WriteLine("通過方法1,{0}已經登記到圖書館了!",bookitem.BookName);
}
public void LoadBook(string bookName,string bookId,int bookValue,string bookAuthor)
{
//Book bookitem = new Book(){...}可以先根據傳進來的圖書參數創建一個新的圖書實例;
Console.WriteLine("通過方法2,{0}已經登記到圖書館了!",bookName);
}
}
public class Book
{
public Book(){}
public Book (string bookName,string bookID,int bookValue):this()
{
this.bookName = bookName;
this.bookID = bookID;
this.bookValue = bookValue;
}
private string bookName;
public string BookName{get;set;}
private string bookAuthor;
public string BookAuthor{get;set;}
private int bookValue;
public string BookValue{get;set;}
private string bookID;
public string BookID{get;set;}
}
public class Student
{
public Student(){}
public Student(string studentName,string studentID):this()
{
this.studentName = studentName;
this.studentID = studentID;
}
private string studentName ;
public string StudentName {get;set;}
private string studentID ;
public string StudentID {get;set;}
}
}
在上面的例子中,定義了三種類,圖書館Library,學生Student,書籍Book,在測試類Test中,進行實例化,並且調用實例library1的兩種登記書籍的方法;這兩個方法就是函數重載的一種,同時可以發現,在學生類和書籍類的構造函數,也可以認爲是一種函數重載的體現,在實際代碼編寫中,我們也可以使用一個方法使用多個默認參數的方法來實現和函數重載相同的效果。
運算符重載,也是相同的道理,本章省略,以後在其他章節詳細介紹。
運行多態性
在這個部分,主要是介紹程序在運行期間同一名稱的方法的不同實現。典型的有類和繼承類之間的方法重寫override(繼承多態性),以及類和接口之間的方法實現(實現多態性 ),可以重寫的方法一般典型的有abstract修飾的抽象方法和使用virtual修飾的虛方法,實現接口的類在其內部必須實現接口的所有成員,就單獨的方法成員來說,感覺接口方法就像抽象類的抽象方法一樣,在定義的時候不能有實現,但是在繼承類中必須有實現。
舉個例子:
比如動物這個抽象類,它有叫(),餵食()等方法,描述具體的一種動物類比如貓,狗等,都繼承自動物這個抽象類,在個自定義中
具體的實現方法有不同。如下代碼:
using system;
namespace TestForPolymorphism
{
class Test
{
static void Main(string[] args)
{
Dog dog1= new Dog();
Cat cat1 = new Cat();
cat1.叫();
dog1.叫();
cat1.餵食();
dog1.餵食(); //繼承多態性
cat1.bear(); //實現多態性
dog1.bear();
Console.ReadKey();
}
}
public abstract class Animal
{
public virtual void 叫(){}
public abstract void 餵食();
}
interface Ibearable
{
void bear();
}
public class Dog:Ibearable,Animal
{
public Dog(){}
public override void 叫()
{ Console.WriteLine("汪") ; }
public void 餵食()
{
Console.WriteLine("喂的狗糧") ;
}
public void bear()
{ Console.WriteLine("生的狗仔") ;}
}
public class Cat:Ibearable,Animal
{
public Cat(){}
public override void 叫()
{ Console.WriteLine("喵") ; }
public void 餵食()
{
Console.WriteLine("喂的貓糧") ;
}
public void bear()
{ Console.WriteLine("生的貓仔") ;}
}
}