重写、重载与动态绑定与多态
一、重载
二、重写
三、动态绑定
四、多态
文章目录
一、重载(overload)
1.重载发生的条件
- 方法名相同
- 参数列表不同(这些方法的形式参数个数、类型)
- 返回值不做要求(传回的值可能各不相同)
2.求和的重载
import java.util.Scanner;
/*求和的重载
* 方法名相同 参数类型和个数不同 构成重载
* */
public class Test {
//两个整数之和
public static int sum(int n, int m) {
int sum = m + n;
return sum;
}
//三个小数之和
public static double sum(double i, double j, double k) {
double sum = i + j + k;
return sum;
}
//main函数
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int a = scan.nextInt();
int b = scan.nextInt();
int ret1 = sum(a, b);
System.out.println(ret1);
double x = scan.nextDouble();
double y = scan.nextDouble();
double z = scan.nextDouble();
double ret2 = sum(x, y, z);
System.out.println(ret2);
}
}
3.分析
二、重写(override)
1.重写发生的条件
- 方法名称相同
- 参数列表也要相同(这些方法的形式参数个数和类型)
- 返回值也要相同 (如果返回值可以构成协变类型也可以发生重写)
协变类型:子类的返回值与父类是继承关系
2.重写需要注意的事项
- 如果当前方法是静态的,则不可以发生重写
- 子类如果重写父类的方法,那么子类的访问修饰权限要大于父类的访问权限(private< default< protected <public)
- 父类当中被重写的方法一定不能是private!!!
- final关键字修饰方法,则方法不能被重写
(final修饰的方法叫——密封方法)
3.重写实例
//父类
class Animal {
public String name;
public int age;
//父类的构造方法 先构造父类
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name+"eat()!");
}
}
//子类
class Dog extends Animal{
public int a;//Dog自己的成员变量
//构造方法
public Dog(String name) {
super(name);
}
public void bark() {
System.out.println(this.name+"wang wang!");
}
@Override //注解用来检查当前方法是否发生重写
public void eat() {
System.out.println(name+"Dog:eat()!");
}
}
class Bird extends Animal {
public Bird(String name) {
super(name);
}
public void fly() {
System.out.println("飞");
}
}
public class TestDemo {
public static void main(String[] args) {
Animal animal = new Dog("huahua");//动态绑定 运行时绑定 animal.eat();//动态绑定
animal.eat();
}
3.分析
三、动态绑定
1.动态绑定发生的条件
- 一定要发生向上转型(父类引用 引用 子类对象)
- 父类和子类有同名的 重写/覆盖/覆写方法
- 最后通过父类的引用来调用子类和父类的这个同名方法
满足以上三个条件此时才会发生动态绑定(或者叫运行时绑定)
2.注意
在构造方法当中也可以发生动态绑定
3.实例
class Animal {
public String name;
public int age;
//父类的构造方法 先构造父类
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name+"eat()!");
}
}
//子类
class Dog extends Animal{
public int a;//Dog自己的成员变量
//构造方法
public Dog(String name) {
super(name);
}
public void bark() {
System.out.println(this.name+"wang wang!");
}
@Override //注解用来检查当前方法是否发生重写
public void eat() {
System.out.println(name+"Dog:eat()!");
}
}
class Bird extends Animal {
public Bird(String name) {
super(name);
}
public void fly() {
System.out.println("飞");
}
}
public class Test {
public static void main3(String[] args) {
Animal animal = new Dog("huahua");
//animal.bark(); animal这个引用 只能访问Animal类特有的
//animal.a;
//向上转型的三个时机
Animal animal2 = new Animal("huahua");
func(animal2);
Dog dog = new Dog("huahua");
func(dog);
func(new Dog("huahua"));
System.out.println("=======================");
Animal animal3 = func2();
}
public static Animal func2() {
Dog dog = new Dog("lala");
return dog;
}
public static void func(Animal animal) {
}
public static void main2(String[] args) {
Animal animal = new Dog("huahua");
if(animal instanceof Bird) {
Bird bird =(Bird)animal;
bird.fly();
}
//向下转型不安全
/*Bird bird =(Bird)animal;
bird.fly();*/
}
public static void main1(String[] args) {
Animal animal = new Dog("huahua");//向上转型
Dog dog = (Dog)animal;//向下转型 不安全
dog.eat();
}
}
四、多态
1.多态的思想
多态就是通过传递给父类对象引用不同的子类对象从而表现出不同的行为,多态可为程序提供更好的可扩展性,同样也可以代码重用。
2.多态发生的条件
- 1.父类引用引用了子类对象 必须发生向上转型
- 2.父类和子类里有同名的覆盖方法(发生方法的重写)
- 3.通过父类引用调用同名的覆盖方法
3.多态的意义
程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
3.多态实例
package demo;
/*
* 多态的实现
* */
//形状的一个类
class Shape {
//打印(画)形状的方法
public void draw() {
}
}
//矩形
class Rectangle extends Shape {
@Override//方法的重写=
public void draw() {
System.out.println("♦");
super.draw();
}
}
//圆形
class Cycle extends Shape{
@Override
public void draw() {
System.out.println("●");
super.draw();
}
}
class Flower extends Shape {
@Override
public void draw() {
System.out.println("🌹");
super.draw();
}
}
/*
* 多态的思想——通过一个方法可以实现打印多种功能
* 产生的条件:
* 1.父类引用引用了子类对象 必须发生向上转型
* 2.父类和子类里有同名的覆盖方法(发生方法的重写)
* 3.通过父类引用调用同名的覆盖方法
* */
public class Test {
//画图的方法
public static void drawMap(Shape shape) {
shape.draw();//父类引用调用draw()同名方法
}
public static void main(String[] args) {
Rectangle rect = new Rectangle();//向上转型
Cycle cycle = new Cycle();
//Flower flower = new Flower();
drawMap(cycle);
drawMap(rect);
drawMap(new Flower());
}
}
4.多态的优点
1. 作用
- 简单的说就是一个接口,多种实现;继承的表现就是多态(没有继承就没有多态。)
- 应用程序不必为每一个派生类编写功能调用,只需要对抽象基类进行处理即可。大大提高程序的可复用性。
- 派生类的功能可以被基类的方法或引用变量所调用,这叫向后兼容,可以提高可扩充性和可维护性。
2.优点:
- 可替换性(可以替换一存在的代码);
- 可扩充性(增加新的子类不影响原有类的特性);
- 接口性;
- 灵活性;
- 简化性