物件導向基礎(1)--繼承 多型 重構
這節課講的是物件導向的幾個基本概念,老師舉了個例子把物件導向的很多東西都連線起來了:動物比賽,每個不同動物都有名字,能發出叫聲等。。。
一.繼承.
第一、子類擁有父類非private的屬性和功能;
第二、子類具有自己的屬性和功能,即子類可以擴充套件父類沒有的屬性和功能;
第三、子類還可以以自己的方式實現父類的功能(方法重寫)
除了private和public外,還有protected表示繼承時子類可以對父類有完全訪問權。 也就是說,protected修飾的類成員,對子類公開,對其它類不公開。
來看個例子:
貓類:
class Cat
{
private int shoutNum = 3;
public int ShoutNum
{
get
{
return shoutNum;
}
set
{
if (value < 10)
{
shoutNum = value;
}
else
{
shoutNum = 10;
}
}
}
private string name = "";
public Cat(string name)
{
this.name = name;
}
public Cat()
{
this.name = "無名";
}
public string Shout()
{
string result = "";
for (int i = 0; i < shoutNum; i++)
{
result += "喵 ";
}
return "我的名字叫" + name + " " + result;
}
}
狗類:
class Dog
{
private int shoutNum = 3;
public int ShoutNum
{
get
{
return shoutNum;
}
set
{
if (value < 10)
{
shoutNum = value;
}
else
{
shoutNum = 10;
}
}
}
private string name = "";
public Dog(string name)
{
this.name = name;
}
public Dog()
{
this.name = "無名";
}
public string Shout()
{
string result = "";
for (int i = 0; i < shoutNum; i++)
{
result += "汪 ";
}
return "我的名字叫" + name + " " + result;
}
}
我們發現這兩個類有很多相同的地方,於是我們把他們相同的地方都弄出來組成一個Animal類: class Animal
{
protected string name = "";//用了protected
public Animal(string name)
{
this.name = name;
}
public Animal()
{
this.name = "無名";
}
protected int shoutNum = 3;
public int ShoutNum
{
get
{
return shoutNum;
}
set
{
shoutNum = value;
}
}
}
於是貓狗類就可以這樣寫:
class Cat : Animal
{
public Cat() : base()
{ }
public Cat(string name) : base(name)
{ }
public string Shout()
{
string result = "";
for (int i = 0; i < shoutNum; i++)
result += "喵 ";
return "我的名字叫" + name + " " + result;
}
}
class Dog : Animal
{
public Dog() : base()
{ }
public Dog(string name) : base(name)
{ }
public string Shout()
{
string result = "";
for (int i = 0; i < shoutNum; i++)
result += "汪 ";
return "我的名字叫" + name + " " + result;
}
}
用UML類圖表示:
繼承優點:繼承使得所有子類公共的部分都放在了父類,使得程式碼得到了共享,這就避免了重複,另外,繼承可使得修改或擴充套件繼承而來的實現都較為容易。
缺點:父類變,則子類不得不變。繼承會破壞包裝,父類實現細節暴露給子類,這其實是增大了兩個類之間的耦合性。
雖然採用了繼承,但子類還是顯得有些複雜,假如現在又有很多牛,羊什麼的來了,那麼這個Shout()函式就會有很多種,顯得有點複雜,怎樣解決???
二.多型.
1.概念:表示不同的物件可以執行相同的動作,但要通過它們自己的實現程式碼來執行。
2.舉例:
有一位父親是有名的藝術家, 六個兒子長大成人, 模仿父親惟妙惟肖。 有一天,父親突然發燒,上不了臺,但是票已經賣了,退票影響聲譽。於是決定讓兒子化了 妝代父親表演。
有以下特點:
第一,子類以父類的身份出現
兒子代表父親表演,化妝後就以父親身份出現了。
第二,子類在工作時以自己的方式來實現
兒子模仿得再好,那也是模仿,兒子只能用自己方式表演父親的作品。
第三,子類以父親的身份出現時,子類特有的屬性和方法不可以使用
兒子有自己的絕活也不能使用。
3.虛方法和方法重寫
虛方法:為了使子類的例項完全接替來自父類的類成員,父類必須將該成員宣告為虛擬的。這是通過在該成員的返回型別之前新增virtual關鍵字來實現的。
方法重寫:子類可以選擇使用override關鍵字,將父類實現替換為它自己的實現,這就是方法重寫override
class Animal
{
……
public virtual string Shout()//虛方法,沒有實現具體功能
{
return "";
}
}
class Cat : Animal//貓類
{
public Cat() : base()
{ }
public Cat(string name) : base(name)
{ }
public override string Shout()//方法重寫
{
string result = "";
for (int i = 0; i < shoutNum; i++)
result += "喵 ";
return "我的名字叫" + name + " " + result;
}
}
class Dog : Animal//狗類
{
public Dog() : base()
{ }
public Dog(string name) : base(name)
{ }
public override string Shout()//方法重寫
{
string result = "";
for (int i = 0; i < shoutNum; i++)
result += "汪 ";
return "我的名字叫" + name + " " + result;
}
}
下面看怎麼例項化來運用這些類的:
private Animal[] arrayAnimal;
private void btnRigister_Click(object sender, EventArgs e)
{
arrayAnimal = new Animal[5];
arrayAnimal[0] = new Cat("小花");
arrayAnimal[1] = new Dog("阿毛");
arrayAnimal[2] = new Dog("小黑");
arrayAnimal[3] = new Cat("嬌嬌");
arrayAnimal[4] = new Cat(“小咪");
}
private void btnMatch_Click(object sender, EventArgs e)
{
foreach (Animal item in arrayAnimal)
{
MessageBox.Show(item.Shout());
}
}
執行結果:
來分析一下多型在記憶體的情況:
多型的原理是當方法被呼叫時,無論物件是否被轉換為其父類,都只有位於物件繼承鏈最末端的方法實現會被呼叫。也就是說,虛方法是按照其執行時型別而非編譯時型別進行動態繫結呼叫的。
當mybc呼叫print()函式時,首先找到父類的Print,父類的print指向子類的print,最終呼叫的是子類的print().
所以現在來了牛羊,我們只需要這樣定義類:
class Cattle : Animal
{
public Cattle() : base()
{ }
public Cattle(string name) : base(name)
{ }
public override string Shout()
{
string result = "";
for (int i = 0; i < shoutNum; i++)
result += “哞";
return "我的名字叫" + name + " " + result;
}
}
class Sheep : Animal
{
public Sheep() : base()
{ }
public Sheep(string name) : base(name)
{ }
public override string Shout()
{
string result = "";
for (int i = 0; i < shoutNum; i++)
result += “咩 ";
return "我的名字叫" + name + " " + result;
}
}
我們發現雖然這樣做了,但還是沒有減少子類程式碼的複雜度,Shout()函式還在子類裡,所以我們希望把Shout()函式弄到父類中去,從而引入重構的概念!
三.重構.
1.概念:
兩個互為兄弟的子類程式碼類似,並非完全相同首先採用Extract Method(提煉函式)區分相同部分和差異部分程式碼,構成單獨函式然後再對提煉的程式碼使用Pull UpMethod(方法上移),將它移入父類
2.對上述Animal進行改進,把子類中的shout()函式(相同部分)放到父類中,在父類中增加一個虛方法(不同部分,需子類實現)
class Animal
{
……
public string Shout()
{
string result = "";
for (int i = 0; i < shoutNum; i++)
result += getShoutSound() + ",";
return "我的名字叫" + name + " " + result;
}
protected virtual string getShoutSound()
{
return "";
}
}
class Cat : Animal
{
public Cat() : base()
{ }
public Cat(string name):base(name)
{
}
protected override string getShoutSound()
{
return "喵";
}
}
class Dog : Animal
{
public Dog() : base()
{ }
public Dog(string name):base(name)
{
}
protected override string getShoutSound()
{
return "汪";
}
}
這樣一來我們的目的就達成了,,由於篇幅太長,分兩篇寫的,請看下篇!
相關文章
- JAVA物件導向基礎--封裝 繼承 多型Java物件封裝繼承多型
- 物件導向三大特性-----封裝、繼承、多型物件封裝繼承多型
- 物件導向三大特徵(封裝/繼承/多型)物件特徵封裝繼承多型
- 【Java】瘋狂Java基礎(一)——物件導向的特徵:繼承、封裝和多型Java物件特徵繼承封裝多型
- 物件導向:繼承物件繼承
- 物件導向--繼承物件繼承
- 物件導向-繼承物件繼承
- php物件導向多繼承實現PHP物件繼承
- [.net 物件導向程式設計基礎] (12) 物件導向三大特性——繼承物件程式設計繼承
- JavaScript物件導向 ~ 原型和繼承(1)JavaScript物件原型繼承
- Golang物件導向_繼承Golang物件繼承
- java物件導向繼承Java物件繼承
- 物件導向之繼承物件繼承
- php物件導向--繼承PHP物件繼承
- [JAVA] Java物件導向三大特徵:封裝、繼承、多型Java物件特徵封裝繼承多型
- python 基礎之繼承、重寫、多繼承Python繼承
- 物件導向的三個基本特徵是:封裝、繼承、多型物件特徵封裝繼承多型
- ~~核心程式設計(五):物件導向——多繼承~~程式設計物件繼承
- 物件導向之_繼承概念物件繼承
- Javascript物件導向與繼承JavaScript物件繼承
- java核心思想物件導向三大特性(封裝,繼承,多型)Java物件封裝繼承多型
- Javascript實現物件導向繼承JavaScript物件繼承
- 21. 物件導向之繼承物件繼承
- [.net 物件導向程式設計基礎] (13) 物件導向三大特性——多型物件程式設計多型
- 12 物件導向基礎-1物件
- Kotlin 物件導向程式設計 (OOP) 基礎:類、物件與繼承詳解Kotlin物件程式設計OOP繼承
- JavaScript物件導向之二(建構函式繼承)JavaScript物件函式繼承
- 25. 企業級開發基礎6:物件導向特徵(繼承)物件特徵繼承
- [.net 物件導向程式設計基礎] (14) 重構物件程式設計
- Cris 的 Scala 筆記整理(八):物件導向中級-繼承和多型筆記物件繼承多型
- Java基礎之淺談繼承、多型Java繼承多型
- 物件導向 -- 三大特性之繼承物件繼承
- 說清楚javascript物件導向、原型、繼承JavaScript物件原型繼承
- 5-Java物件導向-繼承(下)Java物件繼承
- 《JavaScript物件導向精要》之五:繼承JavaScript物件繼承
- java學習——物件導向之繼承Java物件繼承
- JavaScript物件導向—繼承的實現JavaScript物件繼承
- JavaScript物件導向那些東西-繼承JavaScript物件繼承