重写是指继承父类的子类对于父类中已有的方法进行重新编写,对父类继承的方法进行覆盖,重写完毕后只有一个方法在子类中存在。
重载是指子类继承父类的方法与子类自身定义的方法在名字上有重合,但可通过返回值,参数类型,顺序,个数加以区分(Java静态检查去实现),在实际调用与父类重名的子类方法,成为重载。
重写与重载都与子类对父类的继承有关,若父类的方法定义时加上了final关键字,则说明该父类方法无法被子类重写。
重写
重写的原因:
一般来说,父类的方法一般子类都直接继承,不会修改,但有些子类型具有特殊性,父类的方法要适应子类,则就需要重写,我在上一篇文章也讨论过,这时,父类通常只是给出一个空函数,没有具体函数实现,甚至有时只给出一个函数定义,连空函数体也懒得写。这类函数往往具有多样性,父类给出的实际也是该方法的规约与定义,具有给出框架的这样的一个作用。
重写的一些要求:
首先重写不应改变父类方法提供的规约和方法功能的原意,一般来说,我们在重写父类方法时应遵守LSP(里式替换原则)原则,这里我不再赘述,下篇文章我会具体讨论老师课上讲的LSP原则。
在重写父类方法时,我们可以使用super这个关键字来复用父类的方法,帮助我们完成方法的重写。
并且,在子类继承父类后,构造器的编写有时免不了要对继承父类的数据进行赋值,这时同样可以使用super对父类中构造器进行复用。
重载
特殊多态与重载密不可分,特殊多态由重载来定义。
Java的编译器通过静态检查,并且根据参数列表进行方法的最佳匹配。这在编译阶段就已经知道我们要执行的是哪个方法了。
重载的规定:
其中不同的参数列表是指不同的参数类型,不同的参数排列顺序,不同的参数种类,仅仅是参数名字换一下是不行的,编译器会报错。
同时重载也可以发生在父类与子类之间。
重载在我理解下就是写类中两个不同的方法,它们仅仅是重名而已,但我们可以把它们两个区分开来,并且这两个方法的来源不限,既可以是类中新定义的方法之间,也可以是从父类继承的方法与子类方法之间,这样我们就说这两个方法是重载的。
下面是重载与重写的对比
我自己写了两个类用于测试我对重载和重写的一些疑问。
一个类是father
另一个是child
由于之前并没有接触过Java语言,很多Java对于重写的实现我并了解,所以做了这样一个小测试
father类中只有两个简单的方法。一个用于验证重写,一个用于验证重载。
child类中,我对父类的方法进行重写,并写了几个重载的函数,涉及了子类中重载,父子类之间的重载,同时还写了一个隐式重写的例子。
下面测试
这时test是father类,但却用child的构造器构造。
test1为test强转为child类的对象,与test指向同一个对象。
输出结果为:
一个父类对象使用的是子类重写的方法。
但在使用test.时会弹出方法窗口里面只有
同时使用test1.时会弹出方法窗口,里面就有相应的重载函数(可以看到不同的参数列表)和子类中才定义的方法。
再看这一段测试代码
测试结果为
我对此的理解是,因为我用了子类的构造器去构造父类对象,则就在内存中这个实际是子类对象的方法库中挑选父类可以使用的的数据与方法给这个对象用,但子类对父类重写的那些方法,在挑选时自然是在子类已重写好的方法,而不是在父类中定义的方法。同时,又因为这个对象是父类,不允许它使用子类特有的方法,故在test.时列表中不会出现子类的特有方法。而也解释了我们将对象强转为child类时,test.又出现了子类中的方法。
以上仅是我在听完老师讲的OOP课后关于重写和重载的一些想法和理解,免不了出现理解上的错误,望请大家指正批评!