多態(tài):讓一個(gè)對(duì)象能夠變出多種狀態(tài)(類型)溉浙,使用父類類型調(diào)用子類中實(shí)現(xiàn)的方法烫止。
實(shí)現(xiàn)多態(tài)的手段:抽象類、虛方法戳稽、接口
抽象類:
1馆蠕、抽象方法只能出現(xiàn)在抽象類中,但是抽象類中可以包含普通方法(普通方法可以由非抽象類的子類調(diào)用)惊奇。
2互躬、在父類中定義的抽象方法不能實(shí)現(xiàn)(也就是沒有方法體,定義的時(shí)候去掉大括號(hào){})颂郎。
例如:
public abstract class Function{
public void A(){
Console.WriteLine ("A方法是普通方法");
}
public abstract void B(); // 沒有方法體 只有方法名定義
}
3吼渡、抽象類不能實(shí)例化(也就是不能new出來)。
4乓序、抽象類與抽象方法需要添加abstract關(guān)鍵字(如:public abstract Class Person{}诞吱,public abstract void Test();)竭缝。
5房维、子類實(shí)現(xiàn)父類的抽象方法時(shí),需要添加override關(guān)鍵字抬纸。
6咙俩、如果抽象類的子類不是抽象類,那么子類中必須重寫父類抽象類的所有抽象方法。
public abstract class Person{
public void A(){
Console.WriteLine ("A方法是普通方法");
}
public abstract void B(); // 沒有方法體 只有方法名定義
}
public abstract class Teacher:Person{
public abstract void C ();
}
public class Student:Teacher{
public override void B ()// 這里是利用override重寫父類Person中的抽象B方法
{
Console.WriteLine ("這是B方法");
}
public override void C ()// 這里是利用override重寫父類Teacher中的抽象C方法
{
// 因?yàn)镾tudent是普通方法 Teacher是抽象方法 而Teacher的父類Person又是一個(gè)抽象函數(shù)
// 所以Student類必須實(shí)現(xiàn)Teacher類和Person中定義的抽象方法
Console.WriteLine ("這是C方法");
}
}
虛方法
方法替換:(這只是方法的替換 并非是虛方法)
子類繼承父類之后阿趁,可以隱藏父類中的方法膜蛔,在子類中重新實(shí)現(xiàn)(使用關(guān)鍵詞new)
public class Person{
public void A(){
Console.WriteLine ("A方法是父類方法");
}
}
public class Teacher:Person{
public new void A (){//這里使用new關(guān)鍵詞將父類的A方法替換為子類的A方法
Console.WriteLine ("A方法是子類方法");
}
}
舉個(gè)栗子:
Person p1 = new Person ();
p1.A ();// 如果等號(hào)前后定義的類型一致,那么這里的A方法為父類的方法
Teacher t1 = new Teacher ();
t1.A ();// 如果等號(hào)前后定義的類型一致脖阵,那么這里的A方法為子類的方法
Person p2 = new Teacher ();
p2.A ();// 如果使用父類類型變量接收子類類型的對(duì)象皂股,那么此時(shí)方法為父類的方法
運(yùn)行結(jié)果顯示:
虛方法和重寫:
1、用virtual修飾的方法叫虛方法命黔,用override修飾的方法為重寫呜呐。
2、只有方法和屬性才能是虛悍募,字段不能虛蘑辑。
運(yùn)行結(jié)果顯示:
虛方法與抽象類的區(qū)別:
(1)抽象方法必須在抽象類中,而虛方法不用坠宴。
(2)抽象方法在父類中不能實(shí)現(xiàn)洋魂,而虛方法可以實(shí)現(xiàn)。
(3)抽象方法在非抽象子類中必須實(shí)現(xiàn)(至少一個(gè)子類要實(shí)現(xiàn)喜鼓,否則副砍,沒意義),而虛方法不用(虛方法可以使用父類自身的方法)庄岖。
接口
接口的格式可以記成用interface替換Class來定義(interface接口默認(rèn)的訪問修飾符是internal)址晕,如 :public interface A { }
在接口中定義方法:
1、不能給 方法和屬性 添加訪問修飾符顿锰,默認(rèn)都是public谨垃。
2、接口中可以包含方法和屬性硼控,不能包含字段刘陶。
3、在接口中的方法/屬性不能實(shí)現(xiàn)牢撼,如:
public interface A{
void Eat(); //這里是定義一個(gè)方法
float Prise { get ; set; } //這里是定義一個(gè)屬性
}
4匙隔、一旦某個(gè)類實(shí)現(xiàn)了接口,就必須實(shí)現(xiàn)接口中定義的全部成員熏版。
5纷责、不能直接實(shí)例化接口,可以使用接口實(shí)現(xiàn)多態(tài)撼短。
抽象類與接口的相同點(diǎn):
(1) 兩者都包含可以由子類繼承的抽象成員再膳;
(2) 兩者都不直接實(shí)例化。
抽象類與接口的區(qū)別:
(1) 抽象類除擁有抽象成員之外曲横,還可以擁有非抽象成員喂柒;而接口所有的成員都是抽象的不瓶。
(2) 抽象成員可以是私有的,而接口的成員默認(rèn)是公有的灾杰。
(3) 接口中不能含有構(gòu)造函數(shù)蚊丐、析構(gòu)函數(shù)、靜態(tài)成員和常量艳吠。
(4) C#只支持單繼承麦备,即子類只能繼承一個(gè)父類,而一個(gè)子類卻能夠?qū)崿F(xiàn)多個(gè)接口昭娩。
public interface inf1{ //接口1
void Eat(); //這里是定義一個(gè)方法
}
public interface inf2{ //接口2
float Prise { get ; set; } //這里是定義一個(gè)屬性 未對(duì)屬性做特別的限制
}
public class Fruit{ //普通類
public string name;
}
//Fruit是Apple的父類(如果有父類 位置一定排在第一個(gè)) inf1和inf2是Apple實(shí)現(xiàn)的接口 可以有多個(gè)接口
public class Apple:Fruit,inf1,inf2{
private float _prise;
#region inf1 implementation
public void Eat ()
{
Console.WriteLine ("{0}的價(jià)格為{1}元一斤",this.name,this.Prise);//這里的name用到了父類的name字段
}
#endregion
#region inf2 implementation
public float Prise {
get {
return _prise;
}
set {
_prise = value;
}
}
#endregion
public Apple (string name,float prise){
this.name = name;
this._prise = prise;
}
}
class MainClass
{
public static void Main (string[] args)
{
//inf1是接口1 可以接收實(shí)現(xiàn)接口1的類的對(duì)象
inf1 f1 = new Apple ("蘋果",10f);
f1.Eat ();
}
}
運(yùn)行結(jié)果顯示: