小学生之面向对象的三大特征(封装、继承、多态)

在前一篇文章中,我们讲了面向对象的特征之一(封装),那么今天我们来了解面向对象的剩余两大特性。

一、继承
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     }
原文地址:https://www.cnblogs.com/1600kun/p/4641622.html