当前位置: 代码迷 >> C# >> 小学生之面向对象的三大特点(封装、继承、多态)
  详细解决方案

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

热度:108   发布时间:2016-05-05 03:13:24.0
小学生之面向对象的三大特征(封装、继承、多态)

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

一、继承
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+F1016 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             else222             {223                 this.txtLoad.Enabled = false;224             }225         }226     }