【设计模式】重载和重写

一、基本定义

构造函数

构造函数是一种特殊的方法 。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与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)的区别。重载的方法能否根据返回类型进行区分?
答:方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求,不能根据返回类型进行区分。

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨幂等

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值