继承和多态

本文详细介绍了Java中的继承机制,包括继承的定义、语法结构和使用,重点讨论了如何在子类中访问父类的成员变量,以及子类构造方法的使用。此外,还阐述了this和super的关键区别,以及继承过程中的初始化顺序。文章通过多个代码示例展示了继承、多态和重写的概念,并提供了学习小贴士,帮助读者深入理解这些核心概念。
摘要由CSDN通过智能技术生成

文章目录


前言

Java中使用类来对现实世界中的实体进行描述,类经过实例化之后的产物对象,就可以用来表示现实中的实体,但是现实世界错综复杂,事物之间可能会存在一些关联,那在设计程序时就需要考虑到继承问题。

一、继承

1.1 继承的定义

继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特 性的基础上进行扩展,增加新功能,这样产生新的类,称派生类。
继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。

1.2 继承的语法结构

在Java中如果要表示类之间的继承关系,需要借助extends关键字。

语法结构如下:
修饰符 class 子类 extends 父类 {
// … 成员变量/成员 方法
}

1.3 继承的使用

//未使用继承,单独定义多个类
class Dog{
    public String name;
    public int age;
    public String color;

    public void eat(){
        System.out.println(this.name + "正在进食");
    }
    public void bark(){
        System.out.println(this.name + "正在吠叫");
    }
}

class Cat{
    public String name;
    public int age;
    public String color;

    public void eat(){
        System.out.println(this.name + "正在进食");
    }
    public void bark(){
        System.out.println(this.name + "正在吠叫");
    }
}
public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "月饼";
        dog.age = 1;
        dog.color = "黄色";
        dog.eat();
        dog.bark();
        System.out.println("=======================");
        Cat cat = new Cat();
        cat.name = "月亮";
        cat.age = 2;
        cat.color = "黑色";
        cat.eat();
        cat.bark();
    }
}

结果如下在这里插入图片描述

1.3.1 继承代码示例

//子类继承父类后达到了代码复用的效果,子类会继承父类中的成员方法和成员变量,但不会继承静态成员方法,静态成员变量。 
//静态成员方法,静态成员变量 不属于对象所以无法继承。
class Animals{
    public String name;
    public int age;
    public String color;

    public void eat(){
        System.out.println(this.name + "正在进食");
    }
    public void bark(){
        System.out.println(this.name + "正在吠叫");
    }
}
class Dog extends Animals{
    public String sex;
}

class Cat extends Animals{
    public void swap(){
        System.out.println(this.name + "正在摇尾巴");
    }
}
public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "月饼";
        dog.age = 1;
        dog.color = "黄色";
        dog.eat();
        dog.bark();
        System.out.println("=======================");
        Cat cat = new Cat();
        cat.name = "月亮";
        cat.age = 2;
        cat.color = "黑色";
        cat.eat();
        cat.bark();
    }
}

结果如下在这里插入图片描述

1.4 学习小贴士

  1. 子类会将父类中的成员变量或者成员方法继承到子类中。
  2. 子类继承父类之后,必须要新添加自己特有的成员(方法/变量),体现出与基类的不同,否则就没有必要继承。

二、父类成员访问

2.1 子类中访问父类的成员变量

2.1.1 子类和父类不存在同名成员变量(一)

class Base{
    public int a;
    public int b;
}

class Derived extends Base{
    public int c;

    public void method(){
        a = 10;
        b = 20;
        c = 30;
    }
}
public class Test {
    public static void main(String[] args) {
        Derived derived = new Derived();
        derived.method();
        System.out.println(derived.a);
        System.out.println(derived.b);
        System.out.println(derived.c);
    }
}

结果如下在这里插入图片描述

2.1.1 子类和父类不存在同名成员变量(二)

class Base{
    public int a;
    public int b;
}

class Derived extends Base{
    public int c;

    {
        a = 10;
        b = 20;
        c = 30;
    }
}
public class Test {
    public static void main(String[] args) {
        Derived derived = new Derived();
        System.out.println(derived.a);
        System.out.println(derived.b);
        System.out.println(derived.c);
    }
}

结果如下在这里插入图片描述

2.1.2 子类和父类存在同名成员变量(一)

//子类和父类存在同名成员变量时,局部变量优先

class Base{
    public int a = 2;
    public int b = 5;
}

class Derived extends Base{
    public int c = 4;
    public int a = 1;
    public int b = 2;
    
    public void method(){
        System.out.println(this.a);//打印的是子类的成员变量
        System.out.println(this.b);
        System.out.println(this.c);
    }
}
public class Test {
    public static void main(String[] args) {
        Derived derived = new Derived();
        derived.method();
    }
}

结果如下在这里插入图片描述

2.1.2 子类和父类存在同名成员变量(二)

//子类和父类存在同名成员变量时,使用super访问父类

class Base{
    public int a = 2;
    public int b = 5;
}

class Derived extends Base{
    public int c = 4;
    public int a = 1;
    public int b = 2;
    
    public void method(){
       System.out.println(this.a);//打印的是子类的成员变量
        System.out.println(this.b);//打印的是子类的成员变量
        System.out.println(this.c);
        System.out.println(super.a);//打印的是父类的成员变量
        System.out.println(super.b);//打印的是父类的成员变量
    }
}

public class Test {
    public static void main(String[] args) {
        Derived derived = new Derived();
        derived.method();
    }
}

结果如下在这里插入图片描述

2.1.2 子类和父类存在同名成员变量(三)

//子类和父类存在同名成员变量时,使用super访问父类

class Base{
    public int a = 2;
    public int b = 5;
    public int d = 5;
}

class Derived extends Base{
    public int c = 4;
    public int a = 1;
    public int b = 2;
    
    public void method(){
        System.out.println(this.a);
        System.out.println(this.b);
        System.out.println(this.c);
        System.out.println(super.a);//2
        System.out.println(super.b);//5
        System.out.println("=====================");
        System.out.println(this.a);//1
        System.out.println(this.b);//2
        System.out.println(this.c);//4
        System.out.println(this.d);//5
    }
}

public class Test {
    public static void main(String[] args) {
        Derived derived = new Derived();
        derived.method();
    }
}

结果如下在这里插入图片描述

2.1.2 子类和父类存在同名成员变量(四)

class Animals{
    public String name;
    public int age;
    public String color;

    public Animals(){

    }
    public Animals(String name){
        this.name = name;
    }
    public void eat(){
        System.out.println(this.name + "正在进食");
    }
    public void bark(){
        System.out.println(this.name + "正在吠叫");
    }
}
class Dog extends Animals{
    public Dog(){
        super();
    }
    public Dog(String name){
        super(name);
    }
    public String sex;
}

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
    }
}

结果如下在这里插入图片描述

2.2 学习小贴士

1、当子类继承父类的成员方法和成员变量时,如果子类和父类中有同名的成员变量时,this优先访问子类中的成员变量和成员方法,如果想要访问父类就需要使用关键字super。
2、如果子类和父类中没有同名的成员变量和成员方法时,this可以直接调用子类和子类继承到的成员方法和成员变量。

总结:在子类方法中 或者 通过子类对象访问成员时:
如果访问的成员变量子类中有,优先访问自己的成员变量。
如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。

通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到
则访问,否则编译报错。
通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问,如果没有则报错;

与this相似的,super只能在非静态方法中使用。且需要在子类方法中,才能访问父类的成员变量和方法。

三、子类构造方法

在子类构造方法中,并没有写任何关于基类构造的代码,但是在构造子类对象时,先执行基类的构造方法,然后执行子类的构造方法。因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整 。

3.1 子类构造方法代码示例(一)

class Animal{
    public String name;
    public int age;
    public String color;

    public Animal(){

    }
    public void eat(){
        System.out.println(name + "正在吃粮");
    }
    public void swap(){
        System.out.println(name + "正在摇尾巴");
    }
}
class Dog extends Animal{
    {
        name = "初一";
        age = 1;
    }
    public void wangWang(){
        System.out.println(name + "正在汪汪叫");
    }

    public Dog() {
        super();
        System.out.println("姓名:" + name + " 年龄" + age);
    }
}

class Cat extends Animal{
    public void miMi(){
        System.out.println(name + "正在喵喵叫");
    }
}

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Cat cat = new Cat();
    }
}

结果如下在这里插入图片描述

3.1 子类构造方法代码示例(二)

class Animal{
    public String name;
    public int age;
    public String color;

    public Animal(){

    }

    public Animal(String name) {
        this.name = name;
    }

    public Animal(int age) {
        this.age = age;
    }

    public Animal(String name,String color){
        this.name = null;
        this.color = color;
    }

    public void eat(){
        System.out.println(name + "正在吃粮");
    }
    public void swap(){
        System.out.println(name + "正在摇尾巴");
    }
}
class Dog extends Animal{
    public void wangWang(){
        System.out.println(name + "正在汪汪叫");
    }

    {
        name = "初一";
        age = 19;
    }
    public Dog() {
        super();
    }
    public Dog(String name) {
        super(name);
    }

    public Dog(int age) {
        super(age);
    }
    public Dog(String name,String color) {
        super(name,color);
    }

}

class Cat extends Animal{
    {
        name = "初二";
        age = 10;
    }
    public Cat() {
        super();
    }
    public Cat(String name) {
        super(name);
    }

    public void miMi(){
        System.out.println(name + "正在喵喵叫");
    }

    public Cat(String name,String color) {
        super(name,color);
    }

    public Cat(int age) {
        super(age);
    }
}

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();
        dog.swap();
        System.out.println("=============");
        Cat cat = new Cat();
        cat.eat();
        cat.miMi();
    }
}

结果如下在这里插入图片描述

3.1 子类构造方法的使用

学习小贴士:

  1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构
    造方法。
  2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的
    父类构造方法调用,否则编译失败。
  3. 在子类构造方法中,super(…)调用父类构造时,必须是子类构造函数中第一条语句。
  4. super(…)只能在子类构造方法中出现一次,并且不能和this同时出现

四、this 和 super 的区别

super和this都可以在成员方法中用来访问:成员变量和调用其他的成员函数,都可以作为构造方法的第一条语 句,那他们之间有什么区别呢?
【相同点】

  1. this 和 super都是Java中的关键字
  2. this 和 super只能在类的非静态方法中使用,用来访问非静态成员方法和字段
  3. 在构造方法中调用时,this( ) 和 super( )必须是构造方法中的第一条语句,且不能同时存在。

【不同点】

  1. this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员。
  2. 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性。
  3. 在构造方法中:this(…)用于调用本类构造方法,super(…)用于调用父类构造方法,两种调用不能同时在构造 方法中出现。
  4. 构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有。

五、继承当中的初始化顺序

5.1 基类初始化顺序代码示例(一)

class Animal{
    public String name;
    public int age;
    public String color;

    static {
        System.out.println("Animal的静态代码块");
    }

    {
        System.out.println("Animal的实例代码块");
    }

    public Animal(String name,int age,String color){
        this.name = name;
        this.age = age;
        this.color = color;
        System.out.println("姓名:" + name + " 年龄:" + age + " 颜色:" + color);
    }
    public void eat(){
        System.out.println(name + "正在吃粮食");
    }
    public void swap(){
        System.out.println(name + "正在摇尾巴");
    }
}

public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal("Animal",1,"黑色");
        animal.eat();
        animal.swap();
    }
}

结果如下在这里插入图片描述

5.1 基类初始化顺序代码示例(二)

class Animal{
    public String name;
    public int age;
    public String color;

    static {
        System.out.println("Animal的静态代码块");
    }

    {
        System.out.println("Animal的实例代码块");
    }

    public Animal(String name,int age,String color){
        this.name = name;
        this.age = age;
        this.color = color;
        System.out.println("姓名:" + name + " 年龄:" + age + " 颜色:" + color);
    }
    public void eat(){
        System.out.println(name + "正在吃粮食");
    }
    public void swap(){
        System.out.println(name + "正在摇尾巴");
    }
}

public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal("Animal",1,"黑色");
        animal.eat();
        animal.swap();
        System.out.println("==========================");
        Animal animal1 = new Animal("Animal1",2,"白色");
        animal1.eat();
        animal1.swap();
    }
}

结果如下在这里插入图片描述

5.2 子类初始化顺序代码示例(一)


class Animal{
    public String name;
    public int age;
    public String color;

    static {
        System.out.println("Animal的静态代码块");
    }

    {
        System.out.println("Animal的实例代码块");
    }

    public Animal(){

    }

    public Animal(String name,int age,String color){
        this.name = name;
        this.age = age;
        this.color = color;
        System.out.println("Animal的构造函数");
    }

}

class Dog extends Animal{

    static {
        System.out.println("子类的静态代码块");
    }

    {
        name = "初一";
        age = 19;
        System.out.println("子类的示例代码块");
    }
    public Dog(String name,int age,String color) {
        super(name,age,color);
        System.out.println("子类的构造方法");
    }

}

public class Test {
    public static void main(String[] args) {
        Dog dog1 = new Dog("Dog1",2,"白色");
    }
}
//先执行所有的静态代码块,再执行父类的实例化代码块以及父类的构造方法。最后再执行子类的实例化代码和构造方法。
//1. 静态代码块先执行,并且只执行一次,在类加载阶段执行
//2. 当有对象创建时,才会执行实例代码块,实例代码块执行完成后,最后构造方法执行

结果如下在这里插入图片描述

5.2 子类初始化顺序代码示例(二)

class Animal{
    public String name;
    public int age;
    public String color;

    static {
        System.out.println("Animal的静态代码块");
    }

    {
        System.out.println("Animal的实例代码块");
    }

    public Animal(){

    }

    public Animal(String name,int age,String color){
        this.name = name;
        this.age = age;
        this.color = color;
        System.out.println("Animal的构造函数");
    }

}

class Dog extends Animal{

    static {
        System.out.println("子类的静态代码块");
    }

    {
        name = "初一";
        age = 19;
        System.out.println("子类的示例代码块");
    }
    public Dog(String name,int age,String color) {
        super(name,age,color);
        System.out.println("子类的构造方法");
    }

}

public class Test {
    public static void main(String[] args) {
        Dog dog1 = new Dog("Dog1",2,"白色");
        System.out.println("==================");
        Dog dog2 = new Dog("Dog2",1,"黄色");
    }
}

结果如下在这里插入图片描述

5.3 学习小贴士

1、父类静态代码块优先于子类静态代码块执行,且是最早执行。父类实例代码块和父类构造方法紧接着执行。
2、子类的实例代码块和子类构造方法紧接着再执行。
2、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行。

六、 继承方式

6.1 final 关键字

final关键可以用来修饰变量、成员方法以及类。

  1. 修饰变量或字段,表示常量(即不能修改)
  2. 修饰类:表示此类不能被继承。我们平时是用的 String 字符串类, 就是用 final 修饰的, 不能被继承。
  3. 修饰方法:表示该方法不能被重写(
public class Test {
    public static void main(String[] args) {
        int a = 20;
        a = 10;
        System.out.println(a);

        final int b = 10;
        b = 20;//errer
        System.out.println(b);
    }
}

结果如下在这里插入图片描述

6.2 多态

6.2.1多态的概念

通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。

6.2.2 动态绑定代码示例(一)

class Animal{
    public String name;
    public int age;
    public String color;

    public Animal(){

    }

    public Animal(String name) {
        this.name = name;
    }

    public Animal(int age) {
        this.age = age;
    }

    public Animal(String name, String color) {
        this.name = name;
        this.color = color;
    }

    public void eat(){
        System.out.println(name + "正在吃粮 ———— Animal" );
    }
    public void swap(){
        System.out.println(name + "正在摇尾巴———— Animal");
    }
}

class Dog extends Animal{
    public Dog() {
    }
    public Dog(String name){
        super(name);
        this.name = name;
    }
    public Dog(int age){
        super(age);
        this.age = age;
    }
    public Dog(String name,String color){
        super(name,color);
        this.name = name;
        this.color = color;
    }


    public void eat(){
        System.out.println(name + "正在吃狗粮 ———— Dog");
    }

    public void swap(){
        System.out.println(name + "正在摇尾巴 ———— Dog");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal("初三","黄色");
        animal.eat();
        animal.swap();

        System.out.println("================");

        Animal animal1 = new Dog("初一","白色");
        animal1.eat();
        animal1.swap();
    }
}

结果如下在这里插入图片描述

6.2.2 动态绑定代码示例(二)

class Animal {
    public String name;
    public int age;
    public String color;

    public Animal(){

    }

    public Animal(String name){
        this.name = name;
    }

    public Animal(int age){
        this.age = age;
    }

    public Animal(String name,String color){
        this.name = name;
        this.color = color;
    }
    public void eat(){
        System.out.println(name + "正在吃粮");
    }

    public void swap(){
        System.out.println(name + "正在摇尾巴");
    }
}

class Dog extends Animal {
    public Dog(){
        super();
    }

    public Dog(String name){
        super(name);
    }

    public Dog(int age){
        super(age);
    }

    public Dog(String name,String color){
        super(name,color);
    }

    public void wangWang(){
        System.out.println(name + "正在吠叫");
    }
}

class Bird extends  Animal{
    public Bird(){
        super();
    }

    public Bird(String name){
        super(name);
    }

    public Bird(int age){
        super(age);
    }

    public Bird(String name,String color){
        super(name,color);
    }
    public void fly(){
        System.out.println(name + "正在飞翔");
    }
}

    public static void main(String[] args) {
        Animal animal = new Dog(("小鸟");
        Animal animal1 = new Bird(("小鸟");
    }
}

结果如下在这里插入图片描述

6.2.3 动态绑定直接赋值代码示例

class Animal {
    public String name;
    public int age;
    public String color;

    public Animal(){

    }

    public Animal(String name){
        this.name = name;
        System.out.println("姓名:" + name);
    }

    public Animal(int age){
        this.age = age;
        System.out.println("年龄:" + age);
    }

    public Animal(String name,String color){
        this.name = name;
        this.color = color;
        System.out.println("姓名:" + name + "颜色" + color);
    }
    
    public void eat(){
        System.out.println(name + "正在吃粮");
    }

    public void swap(){
        System.out.println(name + "正在摇尾巴");
    }
}

class Dog extends Animal {
    public Dog(){
        super();
    }

    public Dog(String name){
        super(name);
    }

    public Dog(int age){
        super(age);
    }

    public Dog(String name,String color){
        super(name,color);

    }

    public void wangWang(){
        System.out.println(name + "正在吠叫");
    }
}

class Bird extends  Animal {
    public Bird() {
        super();
    }

    public Bird(String name) {
        super(name);
    }

    public Bird(int age) {
        super(age);
    }

    public Bird(String name, String color) {
        super(name, color);
    }

    public void fly() {
        System.out.println(name + "正在飞翔");
    }

    public static void main(String[] args) {
        Animal animal = new Dog("小狗");
        Animal animal1 = new Bird("小鸟");
    }
}

结果如下在这里插入图片描述

6.2.4 动态绑定方法传参代码示例

class Animal {
    public String name;
    public int age;
    public String color;

    public Animal(){

    }

    public Animal(String name){
        this.name = name;
        System.out.println("姓名:" + name);
    }

    public Animal(int age){
        this.age = age;
        System.out.println("年龄:" + age);
    }
    public Animal(String name,String color){
        this.name = name;
        this.color = color;
        System.out.println("姓名:" + name + " 颜色:" + color);
    }
    public void eat(){
        System.out.println(name + "正在吃粮");
    }

    public void swap(){
        System.out.println(name + "正在摇尾巴");
    }
}

class Dog extends Animal {
    public Dog(){
        super();
    }

    public Dog(String name){
        super(name);
    }

    public Dog(int age){
        super(age);
    }

    public Dog(String name,String color){
        super(name,color);
    }

    public void wangWang(){
        System.out.println(name + "正在吠叫");
    }
}

class Bird extends  Animal{
    public Bird(){
        super();
    }

    public Bird(String name){
        super(name);
    }

    public Bird(int age){
        super(age);
    }

    public Bird(String name,String color){
        super(name,color);
    }

    public void fly(){
        System.out.println(name + "正在飞翔");
    }
}

public class Test {
    public static void func(Animal animal){
    }
    public static void main(String[] args) {
        Dog dog = new Dog("初一");
        Bird bird = new Bird("小鸟");
        func(dog);
        func(bird);
    }
}

结果如下在这里插入图片描述

6.2.5 动态绑定返回值代码示例

class Animal {
    public String name;
    public int age;
    public String color;

    public Animal(){

    }

    public Animal(String name){
        this.name = name;
        System.out.println("姓名:" + name);
    }

    public Animal(int age){
        this.age = age;
        System.out.println("年龄:" + age);
    }

    public Animal(String name,String color){
        this.name = name;
        this.color = color;
        System.out.println("姓名:" + name + " 颜色:" + color);
    }
    public void eat(){
        System.out.println(name + "正在吃粮");
    }

    public void swap(){
        System.out.println(name + "正在摇尾巴");
    }
}

class Dog extends Animal {

    public Dog(){
        super();
    }

    public Dog(String name){
        super(name);
    }

    public Dog(int age){
        super(age);
    }

    public Dog(String name,String color){
        super(name,color);
    }

    public void wangWang(){
        System.out.println(name + "正在吠叫");
    }
}

class Bird extends  Animal{

    public Bird(){
        super();
    }

    public Bird(String name){
        super(name);
    }

    public Bird(int age){
        super(age);
    }

    public Bird(String name,String color){
        super(name,color);
    }

    public void fly(){
        System.out.println(name + "正在飞翔");
    }
}

public class Test {
    public static Animal func(){
        return new Dog("初一","黑色");
    }

    public static Animal func1(){
        return new Bird("初二","白色");
    }
    public static void main(String[] args) {
        Animal animal1 = func();
        Animal animal2 = func1();
    }
}

结果如下在这里插入图片描述

6.3 重写

6.3.1 重写的概念

重写(override):也称为覆盖。重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。

6.3.2 方法重写的规则

1、子类在重写父类的方法时,一般必须与父类方法原型一致: 返回值类型 方法名 (参数列表) 要完全一致。
被重写的方法返回值类型可以不同,但是必须是具有父子关系的。
2、访问权限不能比父类中被重写的方法的访问权限更低。private < default < protected < public
3、父类被static、private、final(密封方法)修饰的方法、构造方法都不能被重写。
4、重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验. 例如不小心将方法名字拼写错, 那么此时编译器就会发现父类中没有该方法, 就会编译报错, 提示无法构成重写。

6.4.1 方法重写的代码示例(运行时绑定)

class Animal {
    public String name;
    public int age;
    public String color;

    public Animal(){

    }

    public Animal(String name){
        this.name = name;
    }

    public Animal(int age){
        this.age = age;
        System.out.println("年龄:" + age);
    }

    public Animal(String name,String color){
        this.name = name;
        this.color = color;
        System.out.println("姓名:" + name + " 颜色:" + color);
    }
    public void eat(){
        System.out.println(name + "正在吃粮");
    }

    public void swap(){
        System.out.println(name + "正在摇尾巴");
    }
}

class Dog extends Animal {

    public Dog(){
        super();
    }

    public Dog(String name){
        super(name);
    }

    public Dog(int age){
        super(age);
    }

    public Dog(String name,String color){
        super(name,color);
    }

    public void wangWang(){
        System.out.println(name + "正在吠叫");
    }

    public void eat(){
        System.out.println(name + "正在吃狗粮");
    }
}

class Bird extends  Animal{

    public Bird(){
        super();
    }

    public Bird(String name){
        super(name);
    }

    public Bird(int age){
        super(age);
    }

    public Bird(String name,String color){
        super(name,color);
    }

    public void fly(){
        System.out.println(name + "正在飞翔");
    }
}

public class Test {
    public static void main(String[] args) {
        Animal animal = new Dog("初一");
        animal.eat();//向上转型并调用了子类中父类重写的方法,结果就是调用了子类自己的重写方法
   //在编译时确实认为需要调用父类的eat(),但是运行时发现子类重写了eat(),所以直接调用子类自己的方法。
        Animal animal1 = new Bird("小鸟");
        animal1.eat();//只向上转型,所以仍然调用父类的方法
    }
}

结果如下在这里插入图片描述

6.4 静态绑定与动态绑定

静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表函数重载。
动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用那个类的方法。

6.5 向上转移和向下转型

6.5.1 向上转型

向上转型:实际就是创建一个子类对象,将其当成父类对象来使用。父类类型引用子类对象,从小范围向大范围的转换。
语法格式:父类类型 对象名 = new 子类类型();
向上转型的优点:让代码实现更简单灵活。
向上转型的缺陷:不能调用到子类特有的方法。

6.5.2 向下转型

向下转型:将一个子类对象经过向上转型之后当成父类方法使用,在无法调用子类的方法,但有时候可能需要调用子类特有的方法时,将父类引用再还原为子类对象即可,即向下转换。

6.5.2.1 向下转型错误代码示例

class Animal{
    public String name;
    public int age;
    public String color;

    public Animal(){

    }

    public Animal(String name){
        this.name = name;
    }

    public Animal(int age){
        this.age = age;
        System.out.println("年龄:" + age);
    }

    public Animal(String name,String color){
        this.name = name;
        this.color = color;
        System.out.println("姓名:" + name + " 颜色:" + color);
    }
    public void eat(){
        System.out.println(name + "正在吃粮");
    }

    public void swap(){
        System.out.println(name + "正在摇尾巴");
    }
}

class Dog extends Animal {

    public Dog(){
        super();
    }

    public Dog(String name){
        super(name);
    }

    public Dog(int age){
        super(age);
    }

    public Dog(String name,String color){
        super(name,color);
    }

    public void wangWang(){
        System.out.println(name + "正在吠叫");
    }

    public void eat(){
        System.out.println(name + "正在吃狗粮");
    }
}

class Bird extends  Animal{

    public Bird(){
        super();
    }

    public Bird(String name){
        super(name);
    }

    public Bird(int age){
        super(age);
    }

    public Bird(String name,String color){
        super(name,color);
    }

    public void fly(){
        System.out.println(name + "正在飞翔");
    }
    public static void main(String[] args) {
        Animal animal = new Bird("小鸟");
        Bird bird = (Bird) animal;
        bird.fly();

        Animal animal1 = new Dog("小狗");
            Bird bird1 = (Bird) animal1;
            bird1.fly();
    }
}

结果如下在这里插入图片描述

6.5.2.2 向下转型正确代码示例

class Animal{
    public String name;
    public int age;
    public String color;

    public Animal(){

    }

    public Animal(String name){
        this.name = name;
    }

    public Animal(int age){
        this.age = age;
        System.out.println("年龄:" + age);
    }

    public Animal(String name,String color){
        this.name = name;
        this.color = color;
        System.out.println("姓名:" + name + " 颜色:" + color);
    }
    public void eat(){
        System.out.println(name + "正在吃粮");
    }

    public void swap(){
        System.out.println(name + "正在摇尾巴");
    }
}

class Dog extends Animal {

    public Dog(){
        super();
    }

    public Dog(String name){
        super(name);
    }

    public Dog(int age){
        super(age);
    }

    public Dog(String name,String color){
        super(name,color);
    }

    public void wangWang(){
        System.out.println(name + "正在吠叫");
    }

    public void eat(){
        System.out.println(name + "正在吃狗粮");
    }
}

class Bird extends  Animal{

    public Bird(){
        super();
    }

    public Bird(String name){
        super(name);
    }

    public Bird(int age){
        super(age);
    }

    public Bird(String name,String color){
        super(name,color);
    }

    public void fly(){
        System.out.println(name + "正在飞翔");
    }
    public static void main(String[] args) {
        Animal animal = new Bird("小鸟");
        Bird bird = (Bird) animal;
        bird.fly();

        Animal animal1 = new Dog("小狗");
        if(animal1 instanceof Bird){
            Bird bird1 = (Bird) animal1;
            bird1.fly();
        }else {
            System.out.println("飞不起来");
        }
    }
}

结果如下在这里插入图片描述

6.6 多态代码示例

普通代码(一)

class Shape{
    public void drap(){
        System.out.println("画图形");
    }
}

class Rect extends Shape{
    @Override
    public void drap() {
        System.out.println("◊");
    }
}

class Circle extends Shape{
    @Override
    public void drap(){
        System.out.println("○");
    }
}

class Flower extends Shape{
    @Override
    public void drap(){
        System.out.println("❀");
    }
}

public class Test {

    public static void main(String[] args) {
        Rect rect = new Rect();
        Circle circle = new Circle();
        Flower flower = new Flower();

        String strings[] = {"rect","circle","rect","circle","flower"};
        
        for (String s: strings) {
            if(s.equals("rect")){
                rect.drap();
            } else if (s.equals("circle")){
                circle.drap();
            }else if (s.equals("flower")){
                flower.drap();
            }
        }
    }
}

结果如下在这里插入图片描述

多态代码(一)

class Shape{
    public void drap(){
        System.out.println("画图形");
    }
}

class Rect extends Shape{
    @Override
    public void drap() {
        System.out.println("◊");
    }
}

class Circle extends Shape{
    @Override
    public void drap(){
        System.out.println("○");
    }
}

class Flower extends Shape{
    @Override
    public void drap(){
        System.out.println("❀");
    }
}



public class Test {
    public static void drapMaps() {
        Rect rect = new Rect();
        Circle circle = new Circle();
        Flower flower = new Flower();

        Shape[] shapes = {rect, circle, rect, circle, flower};

        for (Shape shape : shapes) {
            shape.drap();
        }
    }

    public static void main(String[] args) {
        drapMaps();
    }
}

结果如下在这里插入图片描述

普通代码(二)

class Shape{
    public void drap(){
        System.out.println("画图形");
    }
}

class Rect extends Shape{
    @Override
    public void drap() {
        System.out.println("◊");
    }
}

class Circle extends Shape{
    @Override
    public void drap(){
        System.out.println("○");
    }
}

class Flower extends Shape{
    @Override
    public void drap(){
        System.out.println("❀");
    }
}



public class Test {
    public static void drapMaps() {
        Rect rect = new Rect();
        Circle circle = new Circle();
        Flower flower = new Flower();

        String strings[] = {"rect", "circle", "rect", "circle", "flower"};

        for (String s : strings) {
            if (s.equals("rect")) {
                rect.drap();
            } else if (s.equals("circle")) {
                circle.drap();
            } else if (s.equals("flower")) {
                flower.drap();
            }
        }
    }

    public static void main(String[] args) {
        drapMaps();
    }
}

结果如下在这里插入图片描述

多态代码

class Shape{
    public void draw(){
        System.out.println("画图形");
    }
}

class Rect  extends Shape{
    @Override
    public void draw(){
        System.out.println("◊");
    }
}

class Circle extends Shape{
    @Override
    public void draw(){
        System.out.println("○");
    }
}

class Flower extends Shape{
    @Override
    public void draw() {
        System.out.println("❀");
    }
}

public class Test {

    public static void drawMap(Shape shape){
        shape.draw();
    }
    public static void main(String[] args) {
        Rect rect = new Rect();
        Circle circle = new Circle();
        Flower flower = new Flower();

        drawMap(rect);
        drawMap(circle);
        drawMap(flower);
    }
}

结果如下在这里插入图片描述

总结

在书写代码的时候,适当的使用多态是有不少好处的,它不仅能够降低代码的 “圈复杂度”, 避免使用大量的 if - else,也可以让代码的扩展能力更强。
但这并不意味着多态没有缺陷,多态代码的运行效率降低且属性没有多态性,当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性,并且构造方法没有多态性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mo_吉托的莫。

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

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

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

打赏作者

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

抵扣说明:

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

余额充值