你的位置:首页 > ASP.net教程

[ASP.net教程]小学生之面向对象的三大特征(封装、继承、多态)


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

一、继承
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   }