zoukankan      html  css  js  c++  java
  • 小学生之面向对象的三大特征(封装、继承、多态)

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

    一、继承
    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     }
  • 相关阅读:
    团队项目-需求分析报告
    自动化测试框架指南
    一起吐槽接口文档
    居家费拖鞋【FunTester居家日记】
    HTTP接口测试基础【FunTester框架教程】
    Java NIO在接口自动化中应用
    JAVA 可变参数
    HashSet 和 LinkedSet 数据结构
    简单数据结构
    JAVA 迭代器的简单使用
  • 原文地址:https://www.cnblogs.com/1600kun/p/4641622.html
Copyright © 2011-2022 走看看