我筆記本上C#方面的知識(shí)基本上整理的差不多了,所以這個(gè)關(guān)于《C#小知識(shí)》的系列估計(jì)就要完結(jié)了,這個(gè)過(guò)程中謝謝大家一直來(lái)對(duì)于我的支持,你們給我的寶貴的意見(jiàn)對(duì)我?guī)椭艽蟆?/p>
在介紹抽象類(lèi)和抽象方法之前還是先提一下多態(tài)的基本概念。
其實(shí)在上一篇關(guān)于里氏替換原則就已經(jīng)說(shuō)明了多態(tài)的精髓"子類(lèi)對(duì)象可以替換父類(lèi)對(duì)象的位置,而程序的功能不受影響"。還是來(lái)看一段代碼吧:
///
/// Create By:ZhiQiang
/// Create Time:2014-2-9
///
class Person
{
//定義虛方法以備子類(lèi)重寫(xiě),當(dāng)子類(lèi)替換父類(lèi)對(duì)象的位置時(shí),可以表現(xiàn)出多態(tài)
public virtual void Run()
{
Console.WriteLine("我是人,我會(huì)跑!");
}
public virtual void Say()
{
Console.WriteLine("我是人,我會(huì)說(shuō)話(huà)!");
}
}
子類(lèi)的代碼如下:
//定義Teacher類(lèi)繼承Person
class Teacher:Person
{
public override void Run()
{
Console.WriteLine("我是老師,我必須慢速跑");
}
public override void Say()
{
Console.WriteLine("我是老師,我得說(shuō)表?yè)P(yáng)的話(huà)!");
}
}
//定義Student類(lèi)繼承Person
class Student : Person
{
//子類(lèi)重寫(xiě)了父類(lèi)的虛方法
public override void Run()
{
Console.WriteLine("我是學(xué)生,我會(huì)加速跑!");
}
public override void Say()
{
Console.WriteLine("我是學(xué)生,我會(huì)說(shuō)英語(yǔ)!");
}
}
下面需要一個(gè)實(shí)現(xiàn)多態(tài)的類(lèi),代碼如下:
//實(shí)現(xiàn)多態(tài)的類(lèi)
class FeatureHuman
{
///
/// 這個(gè)方法就提現(xiàn)了多態(tài),當(dāng)傳入的是子類(lèi)的對(duì)象的時(shí)候,p指向的是子類(lèi)對(duì)象,就可以調(diào)用子類(lèi)重寫(xiě)父類(lèi)方法后的方法
///
/// 父類(lèi)或者子類(lèi)對(duì)象
public void OutPutFeature(Person p)
{
p.Run();
p.Say();
}
}
主體代碼和實(shí)現(xiàn)多態(tài)的方法如下:
static void Main(string[] args)
{
FeatureHuman fea = new FeatureHuman();
//人的特點(diǎn)
Person p = new Person();
Program pro = new Program();
fea.OutPutFeature(p);
//學(xué)生的特點(diǎn)
Student s = new Student();
fea.OutPutFeature(s);
//老師的特點(diǎn)
Teacher t = new Teacher();
fea.OutPutFeature(t);
Console.ReadKey();
}
運(yùn)行,打印結(jié)果如下:
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/7.1.png" alt="" />
這里可以發(fā)現(xiàn),我們outputFeature方法根據(jù)傳入的實(shí)體對(duì)象不同(父類(lèi)變量指向了子類(lèi)的對(duì)象),而打印出了不同人物的特點(diǎn),這就是多態(tài)。
代碼圖解如下:
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/7.2.png" alt="" />
多態(tài)總結(jié)如下:
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/7.3.png" alt="" />
二,抽象類(lèi)和抽象方法
在C#中使用abstract關(guān)鍵字修飾的類(lèi)和方法,叫做抽象類(lèi)和抽象方法。
1)抽象類(lèi)中可以擁有沒(méi)抽象成員,為了繼承給他的子類(lèi)調(diào)用 (抽象類(lèi)就是為了定義抽象成員,繼承給子類(lèi)去實(shí)現(xiàn),同時(shí)子類(lèi)也可以調(diào)用父類(lèi)的非抽象成員)
abstract class Person
{
//private int nAge;
//abstract string strName;
//抽象類(lèi)可以包含不抽象的成員,可以給繼承的子類(lèi)使用
public void Say()
{
Console.WriteLine("我是父類(lèi),我是人!");
}
public virtual void Sing()
{
Console.WriteLine("我是父類(lèi),我是人,我可以唱歌!");
}
//Run的抽象方法
public abstract void Run();
}
2)抽象類(lèi)中可以有virtual修飾的虛方法
如上面的代碼,在抽象類(lèi)中定義了virtual修飾的方法,編譯通過(guò)。抽象類(lèi)就是為了定義抽象成員,繼承給子類(lèi)去實(shí)現(xiàn),所以子類(lèi)也可以實(shí)現(xiàn)抽象類(lèi)中的虛方法。
3)抽象類(lèi)不能實(shí)例化,因?yàn)橛谐橄蟪蓡T,而抽象成員沒(méi)有方法體,如下圖,
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/7.4.png" alt="" />
4)抽象成員不能私有,如果私有子類(lèi)沒(méi)有辦法訪(fǎng)問(wèn)
我們可以在抽象類(lèi)中定義私有成員,但是沒(méi)有意義。因?yàn)樽宇?lèi)根本訪(fǎng)問(wèn)不到這些私有成員,而抽象類(lèi)本身也不能實(shí)例化,所以私有成員訪(fǎng)問(wèn)不到。
5)子類(lèi)必須重寫(xiě)父類(lèi)的抽象方法
在上面代碼的基礎(chǔ)上,我們定義一個(gè)Student類(lèi),繼承抽象類(lèi),但是不實(shí)現(xiàn)抽象類(lèi)的抽象方法,編譯報(bào)錯(cuò)。代碼如下:
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/7.5.png" alt="" />
6)在子類(lèi)中沒(méi)有辦法通過(guò)base關(guān)鍵字調(diào)用父類(lèi)抽象方法
原理同上,抽象類(lèi)的抽象發(fā)放沒(méi)有實(shí)現(xiàn)語(yǔ)句,就算調(diào)用也沒(méi)有意義。但是可以使用base關(guān)鍵字調(diào)用非抽象方法,代碼如下:
class Program
{
static void Main(string[] args)
{
//Person p = new Person();
Student s = new Student();
s.Run();
Console.ReadLine();
}
}
class Student : Person
{
public override void Run()
{
base.Say();
Console.WriteLine("我是學(xué)生,繼承了父類(lèi),我可以跑!");
}
}
打印結(jié)果如下:
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/7.6.png" alt="" />
抽象類(lèi)思維導(dǎo)圖總結(jié)如下:
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/7.7.png" alt="" />
抽象方法
1)抽象方法必須定義在抽象類(lèi)中,
class Student : Person
{
public abstract void Swiming();
public override void Run()
{
base.Say();
Console.WriteLine("我是學(xué)生,繼承了父類(lèi),我可以跑!");
}
}
代碼編譯會(huì)報(bào)錯(cuò),如下圖:
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/7.8.png" alt="" />
2)抽象方法必須使用關(guān)鍵字修飾,示例代碼如下:
abstract class Person
{
//private int nAge;
//abstract string strName;
//抽象類(lèi)可以包含不抽象的成員,可以給繼承的子類(lèi)使用
public void Say()
{
Console.WriteLine("我是父類(lèi),我是人!");
}
public virtual void Sing()
{
Console.WriteLine("我是父類(lèi),我是人,我可以唱歌!");
}
//Run的抽象方法,不能有方法體,留給子類(lèi)實(shí)現(xiàn)
public abstract void Run();
抽象方法思維導(dǎo)圖總結(jié)如下:
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/7.9.png" alt="" />
那么什么時(shí)候使用抽象類(lèi)呢?
①子類(lèi)必須重寫(xiě)父類(lèi)的方法(相當(dāng)于定義了一個(gè)標(biāo)準(zhǔn),規(guī)范)
②父類(lèi)沒(méi)有必要實(shí)例化,就用抽象類(lèi)
③抽象類(lèi)是為了繼承,為了多態(tài)
最后來(lái)看一個(gè)示例代碼:
定義一個(gè)抽象類(lèi),其中包含抽象方法Run()
abstract class Person
{//Run的抽象方法,只要是繼承我的子類(lèi)都要實(shí)現(xiàn)這個(gè)方法
public abstract void Run();
}
分別定義兩個(gè)子類(lèi),繼承抽象類(lèi)Person
class Student : Person
{
//public abstract void Swiming();
public override void Run()
{
// base.Say();
Console.WriteLine("我是學(xué)生,繼承了父類(lèi),我可以跑!");
}
}
class Worker:Person
{
public override void Run()
{
Console.WriteLine("我是工人,繼承了父類(lèi),我每天在廠區(qū)跑!");
}
}
為了表現(xiàn)多態(tài),我們編寫(xiě)一個(gè)方法如下:
//該方法變現(xiàn)了多態(tài),根據(jù)需要返回子類(lèi)的對(duì)象
public static Person GetEntity(string str)
{
if(str=="學(xué)生")
{
return new Student();
}
else if(str=="工人")
{
return new Worker();
}
return null;
}
main函數(shù)中的代碼如下:
static void Main(string[] args)
{
//不直接實(shí)例化父類(lèi)對(duì)象,只是聲明一個(gè)父類(lèi)對(duì)象的變量來(lái)接收方法的返回值
Person p = GetEntity(Console.ReadLine());
p.Run();
Console.ReadLine();
}
運(yùn)行,分別輸入"工人"和"學(xué)生"的打印結(jié)果如下:
http://wiki.jikexueyuan.com/project/csharp-confusing-concepts-summary/images/7.10.png" alt="" />
到這里這一部分的內(nèi)容就結(jié)束了,希望大家多多提寶貴的意見(jiàn)。