【设计模式】重载和重写

一、基本定义

构造函数

构造函数是一种特殊的方法 。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中 。
特别的,一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们。即构造函数的重载。

重载(Overloading)

方法重载是指同一个类中的多个方法具有相同的名字,但这些方法具有不同的参数列表,及参数的数量或参数的类型不能完全相同。

理解概念:
重载:当年,大街上看到冰淇淋店有一款草莓冰淇淋,对它产生了深深地爱意。事过多年,在同一个地点,遇上了同一款冰淇淋,但此时,再也产生不了当年的爱意。同样的大街(类),同样的冰淇淋(方法),因为条件改变(参数类型),就再也产生不了爱意(返回结果),这时候,我的感情就被重载了(或许是厌恶,或许是无所谓)。

重写(Overriding)

方法重写是存在子父类之间的,子类定义的方法与父类中的方法具有相同的方法名字,相同的参数表和相同的返回类型。

注意:
1. 子类中不能重写父类中的final方法
2. 子类中必须重写父类中abstract方法



二、实现方法

重写(Overriding):

通常,派生类继承基类的方法。因此,在调用对象继承方法的时候,调用和执行的是基类的实现。但是,有时需要对派生类中的继承方法有不同的实现。
例如,假设动物类存在“跑”的方法,从中派生出马和狗,马和狗的跑得形态是各不相同的,因此同样方法需要两种不同的实现,这就需要”重新编写”基类中的方法。”重写”基类方法就是修改它的实现或者说在派生类中重新编写。

重载(Overloading):

在一个类中用相同的名称但是不同的参数类型创建一个以上的过程、实例构造函数或属性。


三、详细理解

范围 方法名 参数列表 修饰符 抛出父类没有的异常 返回类型 与面向对象
重载 同一个类 相同 不同 无关 可以 不同 多态
重写 不同的类 相同 相同 大于父类方法 不可以 相同 继承

重写(Overriding)(又称覆盖)

  1. 父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写(Overriding)。但有时子类并不想原封不动地继承父类的方法,而是想做一定修改,这就需要采用方法重写(Overriding)。
  2. 若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。
  3. 子类函数的访问修饰权限不能少于父类的。
为什么要重写父类的方法
 通常,子类继承父类的方法,在调用对象继承方法的时候,调用和执行的是父类的实现。但是,有时候需要

 对子类中的继承方法有不同的实现方式。例如,假设动物存在“跑”的方法,从中继承有狗类和马类两个子类
如何重写
 A.重写父类的方法要用到override关键字(具有override关键字修饰的方法是对父类中同名方法的新实现)

 B.要重写父类的方法,前提是父类中该要被重写的方法必须声明为virtual或者是abstract类型。给父类中

 要被重写的方法添加virtual关键字表示可以在子类中重写它的实现。(注意:C#中的方法默认并不是

 virtual类型的,因此要添加virtual关键字才能够被重写)

 C.virtual关键字用于将方法定义为支持多态,有virtual关键字修饰的方法称为“虚拟方法”
    [访问修饰符] virtual [返回类型] 方法名(参数列表)

     {

          //虚拟方法的实现,该方法可以被子类重写

     }

重写举例:

    namespace inheritDemo2
    {
          class Employee
          {
              public virtual void EmpInfo()
              {
                  Console.WriteLine("用virtual关键字修饰的方法是虚拟方法");
              }
          }

         class DervEmployee : Employee
         {
             public override void EmpInfo()
             {
                 base.EmpInfo();//base关键字将在下面拓展中提到
                 Console.WriteLine("该方法重写base方法");
             }
         }

         class Test
         {
             static void Main(string[] args)
             {
                DervEmployee objDervEmployee = new DervEmployee();
                objDervEmployee.EmpInfo();

                //注意:objDervEmployee派生类的实例是赋给Employee类的objEmployee的引用,
                  // 所以objEmployee引用调用EmpInfo()方法时 还是调用DervEmployee类的方法
                  Employee objEmployee = objDervEmployee;
                objEmployee.EmpInfo();
              }
         }
     }

拓展 :base关键字用于从子类中访问父类成员。即使父类的方法在子类中重写,仍可以使用base关键字调用。
而且,在创建子类实例时,可以使用base关键字调用父类的构造函数。使用base关键字只能访问父类的构造函数、实例方法或实例属性,而不能访问基类的静态方法。


重载(Overloading)

  1. 方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数、类型。重载是一个类中多态性的一种表现。
  2. 重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不同。无法以返回类别作为重载函数的区分标准。

四、总结规则

(一)重写(覆盖)的规则: 
1、重写方法的参数列表必须完全与被重写的方法的相同,否则不能称其为重写而是重载. 
2、重写方法的访问修饰符一定要大于被重写方法的访问修饰符(public>protected>default>private)。 
3、重写的方法的返回值必须和被重写的方法的返回一致或者兼容; 
4、重写的方法所抛出的异常必须和被重写方法的所抛出的异常一致,或者是其子类; 
5、被重写的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行重写; 
6、静态方法不能被重写为非静态的方法(会编译出错); 
7、父类方法被final时,无论该方法被publicprotected及默认所修饰,子类均不能重写该方法。
(二)重载的规则: 
1、在使用重载时只能通过相同的方法名、不同的参数形式实现。不同的参数类型可以是不同的参数类型,不同的参数个数,不同的参数顺序(参数类型必须不一样); 
2、不能通过访问权限、返回类型、抛出的异常进行重载; 
3、方法的异常类型和数目不会对重载造成影响。

五、文末有彩蛋

面试题:重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?
答:方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求,不能根据返回类型进行区分。

你可能感兴趣的:(计算机基础,设计模式)