Java之面向对象多态 ------重载与重写的关系


转发整理于

浅谈重写和重载的区别 - 知乎 (zhihu.com)

Java 重写(Override)与重载(Overload) | 菜鸟教程 (runoob.com)

 

(一)现象:

重写:

   重写(Override)是父类与子类之间多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Override)。

  

重载:

   重载(Overload)是一个类中多态性的一种表现。如果在一个类中定义了多个同名的方法,它们参数列表不同,则称为方法的重载(Overload)

重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。

 

(二)具体区别:

重载(Overload)

1、  重载实现于一个类中;重写实现于子类中。

2、  重载(Overload):是一个类中多态性的一种表现,指同一个类中不同的函数使用相同的函数名,但是函数的参数个数或类型不同。

  可以有不同的返回类型;

  可以有不同的访问修饰符;

  可以抛出不同的异常(被重载的方法可以声明新的或更广的检查异常);

  调用的时候根据函数的参数来区别不同的函数。

重写(Override)

3、  重写(Override): 是父类与子类之间的多态性,是子类对父类函数的重新实现。函数名和参数与父类一样,子类与父类函数体内容不一样。

  子类返回的类型必须与父类保持一致;

  子类方法访问修饰符的限制一定要大于父类方法的访问修饰(public>protected>default>private);

  子类重写方法一定不能抛出新的检查异常或者比被父类方法申明更加宽泛的检查型异常。(重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。)

    例如: 父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,只能抛出 IOException 的子类异常。

 子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。(由于在编译阶段,只是检查参数的引用类型。然而在运行时,Java 虚拟机(JVM)指定对象的类型并且运行对象的方法。)

如果子类需要调用父类中重写的方法,那么就要借助super关键字进行对象声明,从而实现父类中重写的方法。

Test1

class Animal{

 public void move(){

 System.out.println("动物可以移动");

  } 

class Dog extends Animal{

 public void move(){ 

System.out.println("狗可以跑和走");

}

 public class TestDog{

 public static void main(String args[]){

 Animal a = new Animal(); // Animal 对象 

Animal b = new Dog(); // Dog 对象 

a.move();// 执行 Animal 类的方法

b.move();//执行 Dog 类的方法 

}

 }

Sout :

动物可以移动

狗可以跑和走

 

 

Test2

class Animal{

 public void move(){

 System.out.println("动物可以移动");

 } 

class Dog extends Animal{

 public void move(){ 

System.out.println("狗可以跑和走");

public void bark(){

 System.out.println("狗可以吠叫");

public class TestDog{

 public static void main(String args[]){ 

Animal a = new Animal(); // Animal 对象 

Animal b = new Dog(); // Dog 对象 

A.move();// 执行 Animal 类的方法 

b.move();//执行 Dog 类的方法 

b.bark(); } }

Sout:

    TestDog.java:30: cannot find symbol

symbol  : method bark()

location: class Animal

                b.bark();

                 ^

 

 

 

原因:

在Test1的例子中可以看到,尽管 b 属于 Animal 类型,但是它运行的是 Dog 类的 move方法。

这是由于在编译阶段,只是检查参数的引用类型。

然而在运行时,Java 虚拟机(JVM)指定对象的类型并且运行该对象的方法。

因此在上面的例子中,之所以能编译成功,是因为 Animal 类中存在 move 方法,然而运行时,运行的是特定对象的方法。

Thinking:

思考Test2例子:

 

区别点

重载方法

重写方法

参数列表

必须修改

一定不能修改

返回类型

可以修改

一定不能修改

异常

可以修改

可以减少或删除,一定不能抛出新的或者更广的异常

访问

可以修改

一定不能做更严格的限制(可以降低限制)

总结

方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。

(1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。

(2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。

(3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。

(三)代码实现

重载

package com.etime09;

 

public class Goods {  //创建一个商品类

private String ID;

private int price;

private String name;

private String manufactureDate;

//实现构造函数的重载 参数个数或类型不同

public Goods() {

super();

// TODO Auto-generated constructor stub

}

public Goods(String iD) {

super();

ID = iD;

}

public Goods(String iD, int price) {

super();

ID = iD;

this.price = price;

}

public Goods(String iD, int price, String name) {

super();

ID = iD;

this.price = price;

this.name = name;

}

public Goods(String iD, int price, String name, String manufactureDate) {

super();

ID = iD;

this.price = price;

this.name = name;

this.manufactureDate = manufactureDate;

}

 

}

重写

package com.etime09;

 

public class Person {  //创建一个父类Person

private String name;

private int age;

//父类中写一个eat()方法

public void eat() {

System.out.println("人都要吃饭");

}

}

---------------------------------------------

package com.etime09;

 

public class Student extends Person {  //Student子类继承Person父类

@Override

//重写eat()方法   方法名,参数,返回类型相同;方法体内容不同

public void eat() {

System.out.println("学生喜欢吃肉");

}

}