在前一篇文章中,我們講了面向對象的特征之一(封裝),那麼今天我們來了解面向對象的剩余兩大特性。
一、繼承 1、定義 繼承就是從父類中獲取一些公開的成員,如方法和屬性。C#中只允許繼承一個父類,但允許繼承多個接口。如果子類繼承接口,則必須實現接口中定義的所有公開成員。 公開成員是指在父類中定義為public的成員(public的作用域可在子類中生效,而private作用域則不可) 子類繼承父類: 子類擁有父類非Private的屬性和功能; 子類具有自己的屬性和功能,即子類可以擴展父類沒有的屬性和功能; 子類還可以以自己的方式實現父類的功能(方法重寫)2、繼承的兩大特性:
001. 單根性:一個子類不能同時繼承多個父類。
002. 傳遞性:如果有一個類A繼承與類B,又有一個類C繼承與類A,那麼類C也可以使用類B中非私有的字段,屬性和方法。
3.子類構造執行流程?
解析: 第一步:先進入子類構造參數列表
第二步:進入父類對應的構造
第三步:執行父類構造的方法體
第四步:回到子類方法體執行.
4、優點 繼承使得所有子類公共部分都放在父類中,使得代碼得到共享,這就避免了重復。此外,繼承可使得修改或擴展繼承而來的實現都較為容易。 5、注意 Protected表示繼承時子類可以對基類有完全訪問權。也就是說protected修飾的類成員,對子類公開,段不對其他類公開。 實例: 1 private void button1_Click(object sender,EventArgs e)
2
3 {
4
5 Cat cat = new Cat("咪咪");//將類實例化 Cat cat聲明一個Cat對象,對象名為cat;newCat()將此cat對象實例化
6
7 cat.ShoutNum = 5; //給屬性賦值
8
9 MessageBox.Show(cat.Shout());
10
11 }
12
13 class Animal //定義父類
14
15 {
16
17 protected string name =""; //注意變為Protected 子類可以繼承
18
19 public Animal(string name)
20
21 {
22
23 this.name = name;
24
25
26
27 }
28
29 public Animal()
30
31 {
32
33 this.name = "無名";
34
35 }
36
37 protected int shoutNum = 3; //變為protected
38
39 public int ShoutNum
40
41 {
42
43 get
44
45 {
46
47 return shoutNum;
48
49 }
50
51 set
52
53 {
54
55 shoutNum = value;
56
57 }
58
59 }
60
61 }
62
63 class Cat : Animal //注意變化
64
65 {
66
67 public Cat() : base() //子類構造方法需要調用父類同樣參數類型的構造方法,用base關鍵字代表父類
68
69 { }
70
71 public Cat(string name):base(name) //注意變化
72
73 { }
74
75 public string Shout()
76
77 {
78
79 string result = "";
80
81 for (int i = 0; i <shoutNum; i++)
82
83 result += "喵!";
84
85 return "我的名字叫:" +name + "" + result;
86
87 }
88
89 }
90
91 class Dog : Animal //注意變化
92
93 {
94
95 public Dog() : base()
96
97 { }
98
99 public Dog(string name): base(name)
100
101 { }
102
103 public string shout()
104
105 {
106
107 string result = "";
108
109 for (int i = 0; i <shoutNum; i++)
110
111 result += "汪!";
112
113 return "我的名字叫:" +name + "" + result;
114
115 }
116
117 }
118
119 private void button2_Click(objectsender, EventArgs e)
120
121 {
122
123 Dog dog = new Dog("狗");//將類實例化 Cat cat聲明一個Cat對象,對象名為cat;newCat()將此cat對象實例化
124
125 dog.ShoutNum = 5; //給屬性賦值
126
127 MessageBox.Show(dog.shout());
128
129 }
二、多態
1、定義 多態是指類可以有多種形態,通過修改可以形成多個實現方法。子類從父類繼承時它會獲得父類的所有方法、字段、屬性、事件。多態表示不同的對象可以執行相同的操作,但要通過它們自己的實現代碼來執行。通俗的說:不同的對象對於同一個指令做出的響應不同,就是多態。 若要改變父類的數據和行為,兩種方式:可創建新的成員替換父級成員,或者可以重寫虛擬的父級成員。 (1)若要替換父級成員,需要使用new關鍵字。下面是GetName方法的兩種形態,一種是返回父級名稱,一種是返回子級名稱。 1 第一種:返回父級名稱
2
3 class PerentClass //父類
4
5 {
6
7 public string GetName()
8
9 {
10
11 return"父級名稱";
12
13 }
14
15 }
16
17 第二種:返回子級名稱
18
19 class SonClass:PerentClass //子類繼承父類
20
21 {
22
23 public new string GetName()
24
25 {
26
27 return"子級名稱";
28
29 }
30
31 }
32
(2)重寫虛擬的父級成員的兩個條件:父級成員使用關鍵字“virtual”;子級成員使用“override”。
1 class PerentClass //父類
2
3 {
4
5 public virtual string GetName()
6
7 {
8
9 return"父級名稱";
10
11 }
12
13 }
14
15
16
17 class SonClass:PerentClass //子類繼承父類
18
19 {
20
21 public override string GetName()
22
23 {
24
25 return"子級名稱";
26
27 }
28
29 }
(2):抽象方法實現多態
1 /// <summary>
2 /// 鳥類:基類
3 /// </summary>
4 public abstract class Bird
5 {
6 /// <summary>
7 /// 吃:抽象方法
8 /// </summary>
9 public abstract void Eat();
10 }
1 /// <summary>
2 /// 喜鵲:子類
3 /// </summary>
4 public class Magpie:Bird
5 {
6 /// <summary>
7 /// 重寫父類中Eat方法
8 /// </summary>
9 public override void Eat()
10 {
11 Console.WriteLine("我是一只喜鵲,我喜歡吃蟲子~");
12 }
13 }
1 /// <summary>
2 /// 老鷹:子類
3 /// </summary>
4 public class Eagle:Bird
5 {
6 /// <summary>
7 /// 重寫父類中Eat方法
8 /// </summary>
9 public override void Eat()
10 {
11 Console.WriteLine("我是一只老鷹,我喜歡吃肉~");
12 }
13 }
1 /// <summary>
2 /// 企鵝:子類
3 /// </summary>
4 public class Penguin:Bird
5 {
6 /// <summary>
7 /// 重寫父類中Eat方法
8 /// </summary>
9 public override void Eat()
10 {
11 Console.WriteLine("我是一只小企鵝,我喜歡吃魚~");
12 }
13 }
1 static void Main(string[] args)
2 {
3 //創建一個Bird基類數組,添加 Magpie對象,Eagle對象,Penguin對象
4 Bird[] birds = {
5 new Magpie(),
6 new Eagle(),
7 new Penguin()
8 };
9 //遍歷一下birds數組
10 foreach (Bird bird in birds)
11 {
12 bird.Eat();
13 }
14 Console.ReadKey();
15 }
執行結果:

2,抽象類可以被繼承嗎?
可以,不僅可以被普通類繼承,也可以被抽象類繼承
3,抽象方法可以有方法體嗎?
不可以,連花括號都不能有
4,簡述抽象方法和虛方法的區別?
1 //01.定義一個抽象類,用abstract 修飾
2
3 //02.抽象方法不能有方法體,甚至連{}都不能有
4
5 //03.抽象方法只能存在於抽象類中,但是抽象類中可以有非抽象方法
6
7 //04.抽象類不能實例化
8
9 //05.抽象類中抽象方法只是用來規定方法的形式(參數,返回值),約束子類方法的形式
10
11 //06.抽象類中的抽象成員必須在子類中全部實現,除非子類也是抽象類
12
13 //07.子類實現抽象方法的快捷鍵,Ctrl+.(沒有輸入法情況下 )
14
15 //shift+alt+F10
16
17 //08.抽象類不能用static修飾:如果是static,抽象就無法被繼承,也就失去了抽象類本身的意義
5、注意 子類以父類省份出現 子類在工作中以自己的方式來實現 子類乙父類的身份出現時,子類特有的屬性和方法不可同時使用 使用多態時,需了解:虛方法和方法重寫 為了使子類的實例完全接替來自父類的成員,父類必須將該成員聲明為虛擬的。這是通過在該成員的返回類型之前添加virtual來實現。 子類選擇使用override關鍵字,將父類實現替換為自己的實現,這就是方法重寫。 說了這麼多,那麼我們用一個具體案例實現一下吧! 程序效果圖如下:







關鍵代碼如下:
//父類
public abstract class Vehicle//抽象類
{
public string Color { get; set; }//顏色
public double DailyRent { get; set; }//租金
public string LiceseNo { get; set; }//車牌號
public string Name { get; set; }//車名
public int RentDate { get; set; }//租用天數
public string RentUser { get; set; }//租用者
public int YearsOfService { get; set; }//使用時間
public Vehicle() { }
public Vehicle(string color,double dailyRent,string liceseNo,string name,int yearOfSerivce) //父類中的帶參數構造
{
this.Color = color;
this.DailyRent = dailyRent;
this.LiceseNo = liceseNo;
this.Name = name;
this.YearsOfService = yearOfSerivce;
}
public abstract double CalPrice();//父類中計算租車金額的抽象方法
}
1 //子類繼承父類Vehicle
2 class Car:Vehicle
3 {
4 public Car(){}
5 public Car(string color, double dailyRent, string liceseNo, string name,int yearOfSerivce)
6 : base(color,dailyRent,liceseNo,name,yearOfSerivce) //給父類中的各個屬性復制
7 {
8
9 }
10 public override double CalPrice()//重寫父類中租車的抽象方法
11 {
12 double price = base.RentDate * base.DailyRent;
13 return price;
14 }
15 }
1 //子類Trcuk繼承父類Vehicle
2 public class Truck:Vehicle
3 {
4 private int load;//卡車的載重量
5
6 public int Load//封裝字段
7 {
8 get { return load; }
9 set { load = value; }
10 }
11 public Truck(int load, string color, double dailyRent, string liceseNo, string name, int yearOfSerivce)
12 : base(color, dailyRent, liceseNo, name, yearOfSerivce)
13 {
14 this.Load = load;
15 }
16 public Truck() { }
17 public override double CalPrice()//卡車類重寫父類中計算租車金額的抽象方法
18 {
19 double price = base.RentDate * base.DailyRent;
20 return price;
21 }
22 }
1 public partial class Form1 : Form
2 {
3 public Form1()
4 {
5 InitializeComponent();
6 }
7 //保存可租用車集合信息
8 Dictionary<string, Vehicle> vehicles = new Dictionary<string, Vehicle>();
9 //保存租出車輛信息
10 Dictionary<string, Vehicle> rentVehicles = new Dictionary<string, Vehicle>();
11 /// <summary>
12 /// 初始化幾個可租用車信息
13 /// </summary>
14 private void Initail()
15 {
16 Car car = new Car();
17 car.LiceseNo = "京RO123456";
18 car.Name = "奧迪A6";
19 car.Color= "黑色";
20 car.YearsOfService = 3;
21 car.DailyRent = 250;
22 Car car1 = new Car();
23 car1.LiceseNo = "京B32197";
24 car1.Name = "大眾2000";
25 car1.Color = "藍色";
26 car1.YearsOfService = 3;
27 car1.DailyRent = 450;
28 Truck truck = new Truck();
29 truck.LiceseNo = "豫S46541";
30 truck.Name = "東風";
31 truck.Color = "藍色";
32 truck.YearsOfService = 2;
33 truck.DailyRent = 500;
34 truck.Load = 20;
35 vehicles.Add(car.LiceseNo,car);
36 vehicles.Add(car1.LiceseNo,car1);
37 vehicles.Add(truck.LiceseNo,truck);
38 }
39 private void Form1_Load(object sender, EventArgs e)
40 {
41 Initail();
42
43 this.txtLoad.Enabled = false;
44 }
45 /// <summary>
46 /// 更新可租車輛數據
47 /// </summary>
48 private void UpdatelvRent()
49 {
50 this.lvRent.Items.Clear();
51
52 foreach (Vehicle item in vehicles.Values)//循環遍歷集合中的數據,添加到ListView空間中
53 {
54 ListViewItem lvitem = new ListViewItem(item.LiceseNo);
55 if (item is Car)//判斷item是否是Car類形
56 {
57 lvitem.SubItems.Add(item.Name);
58 lvitem.SubItems.Add(item.Color);
59 lvitem.SubItems.Add(item.YearsOfService.ToString());
60 lvitem.SubItems.Add(item.DailyRent.ToString());
61
62 }
63 if (item is Truck)
64 {
65 lvitem.SubItems.Add(item.Name);
66 lvitem.SubItems.Add(item.Color);
67 lvitem.SubItems.Add(item.YearsOfService.ToString());
68 lvitem.SubItems.Add(item.DailyRent.ToString());
69 lvitem.SubItems.Add(((Truck)item).Load.ToString());
70 }
71
72 this.lvRent.Items.Add(lvitem);
73 }
74 }
75 private void btnQueryRent_Click(object sender, EventArgs e)//點擊刷新按鈕事件,調用刷新租車信息方法
76 {
77 UpdatelvRent();
78 }
79
80 private void btnRent_Click(object sender, EventArgs e)//點擊租車按鈕事件
81 {
82 if (this.lvRent.SelectedItems.Count > 0 )//判斷是否是選中的租車信息
83 {
84 if ( this.txtRenter.Text == string.Empty)//租車者不能為空
85 {
86 MessageBox.Show("租用者不能為空!!");
87 return;
88 }
89 foreach (Vehicle item in vehicles.Values)
90 {
91 if (item is Car)//判斷item是否是Car類形
92 {
93 if (this.lvRent.SelectedItems[0].SubItems[0].Text == item.LiceseNo)
94 {
95 vehicles[this.lvRent.SelectedItems[0].SubItems[0].Text].RentUser = this.txtRenter.Text;
96 rentVehicles.Add(item.LiceseNo, item);//添加到租車車輛信息的集合中
97 vehicles.Remove(item.LiceseNo);//從可租車輛信息的集合中刪除選中的車輛信息
98 MessageBox.Show("租車成功!!!");
99 this.txtRenter.Text = "";
100 break;
101 }
102 }
103 if (item is Truck)//同理之上
104 {
105 if (this.lvRent.SelectedItems[0].SubItems[0].Text == ((Truck)item).LiceseNo)
106 {
107 vehicles[this.lvRent.SelectedItems[0].SubItems[0].Text].RentUser = this.txtRenter.Text;
108
109 vehicles.Remove(((Truck)item).LiceseNo);
110 rentVehicles.Add(((Truck)item).LiceseNo, item);
111 MessageBox.Show("租車成功!!!");
112 this.txtRenter.Text = "";
113 break;
114 }
115 }
116
117 }
118 UpdatelvRent();//刷新數據
119 }
120 else
121 {
122 MessageBox.Show("請選擇一輛車租");
123 }
124
125
126 }
127
128 private void btnExit_Click(object sender, EventArgs e)//點擊退出按鈕事件
129 {
130 this.Close();
131 }
132 /// <summary>
133 /// 更新還車信息
134 /// </summary>
135 private void UpdateLvRentu()
136 {
137 this.lvReturn.Items.Clear();
138 foreach (Vehicle item in rentVehicles.Values)
139 {
140 ListViewItem lvitem = new ListViewItem(item.LiceseNo);
141 if (item is Car)
142 {
143 lvitem.SubItems.Add(item.Name);
144 lvitem.SubItems.Add(item.Color);
145 lvitem.SubItems.Add(item.YearsOfService.ToString());
146 lvitem.SubItems.Add(item.DailyRent.ToString());
147
148 }
149 if (item is Truck)
150 {
151 lvitem.SubItems.Add(item.Name);
152 lvitem.SubItems.Add(item.Color);
153 lvitem.SubItems.Add(item.YearsOfService.ToString());
154 lvitem.SubItems.Add(item.DailyRent.ToString());
155 lvitem.SubItems.Add(((Truck)item).Load.ToString());
156 }
157
158 this.lvReturn.Items.Add(lvitem);
159 }
160 }
161 private void btnQueryReturn_Click(object sender, EventArgs e)
162 {
163
164 UpdateLvRentu();
165 }
166
167 private void btnCompute_Click(object sender, EventArgs e)
168 {
169 if (this.lvReturn.SelectedItems.Count > 0)//必須有選中的車輛
170 {
171 if (this.txtRentDate.Text==string.Empty)//租車天數不能為空
172 {
173 MessageBox.Show("請輸入租車天數!!");
174 return;
175 }
176 rentVehicles[this.lvReturn.SelectedItems[0].SubItems[0].Text].RentDate = Convert.ToInt32(this.txtRentDate.Text);
177 double price = rentVehicles[this.lvReturn.SelectedItems[0].SubItems[0].Text].CalPrice();
178 MessageBox.Show("您的總價是" + price.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);//顯示租車金額
179 if (rentVehicles.ContainsKey(this.lvReturn.SelectedItems[0].SubItems[0].Text))//判斷租出車輛信息集合中是否存在還車的車輛
180 {
181
182 vehicles.Add(rentVehicles[this.lvReturn.SelectedItems[0].SubItems[0].Text].LiceseNo, rentVehicles[this.lvReturn.SelectedItems[0].SubItems[0].Text]);//再度添到可租車輛集合中
183 rentVehicles.Remove(this.lvReturn.SelectedItems[0].SubItems[0].Text);//從租出車輛集合中移除
184 }
185 UpdateLvRentu();//刷新信息
186 }
187 else
188 {
189 MessageBox.Show("請選擇一輛車進行歸還!!");
190 }
191
192 }
193
194 private void btnAdd_Click(object sender, EventArgs e)
195 {
196
197 if (this.rdoCar.Checked)//判斷哪個按鈕選中,添入不同的車輛信息
198 {
199
200 Car car = new Car(this.cobColor.Text, Convert.ToInt32(this.txtLetting.Text), this.txtAutoNum.Text, this.txtName.Text,Convert.ToInt32(this.txtYears.Text));
201 vehicles.Add(this.txtName.Text, car);
202 MessageBox.Show("入庫成功!!");
203 }
204 else
205 {
206 this.txtLoad.Enabled = true;
207 Truck car = new Truck(Convert.ToInt32(this.txtLoad.Text), this.cobColor.Text, Convert.ToInt32(this.txtLetting.Text), this.txtAutoNum.Text, this.txtName.Text, Convert.ToInt32(this.txtYears.Text));
208 vehicles.Add(this.txtName.Text, car);
209 MessageBox.Show("入庫成功!!");
210 }
211
212 }
213
214 private void rdoTruck_CheckedChanged(object sender, EventArgs e)//單選鈕點擊改變事件,將載重文本框設為可用
215 {
216 if (this.rdoTruck.Checked)
217 {
218 this.txtLoad.Enabled = true;
219
220 }
221 else
222 {
223 this.txtLoad.Enabled = false;
224 }
225 }
226 }