java继承和多态详解

简介: java继承和多态详解

前言

继承和多态刚开始是比较难理解的,要做到多看,多敲代码。

一、继承

有的时候客观事物之间就存在一些关联关系, 那么在表示成类和对象的时候也会存在一定的关联。

为了方便理解,我们先看下面一段代码。

(1)例如, 设计一个类表示动物

// Animal.java 
public class Animal { 
    public String name; 
    public Animal(String name) { 
this.name = name; 
    } 
    public void eat(String food) { 
        System.out.println(this.name + "正在吃" + food); 
    } 
} 
// Cat.java 
class Cat { 
public String name; 
    public Cat(String name) { 
this.name = name; 
    } 
    public void eat(String food) { 
        System.out.println(this.name + "正在吃" + food); 
    } 
} 
// Bird.java 
class Bird { 
public String name; 
    public Bird(String name) { 
        this.name = name; 
    } 
} 
    public void eat(String food) { 
        System.out.println(this.name + "正在吃" + food); 
    } 
    public void fly() { 
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿"); 
    }

仔细分析, 我们发现 Animal 和 Cat 以及 Bird 这几个类中存在一定的关联关系:

1)这三个类都具备一个相同的 eat 方法, 而且行为是完全一样的.

2)这三个类都具备一个相同的 name 属性, 而且意义是完全一样的.

(2)语法规则

class 子类 extends 父类 { 
} 

对于上面的代码, 可以使用继承进行改进. 此时我们让 Cat 和 Bird 继承自 Animal 类, 那么 Cat 在定义的时候就不必再写 name 字段和 eat 方法。

class Animal { 
    public String name; 
    public Animal(String name) { 
        this.name = name; 
    } 
    public void eat(String food) { 
        System.out.println(this.name + "正在吃" + food); 
    } 
} 
class Cat extends Animal { 
    public Cat(String name) { 
        // 使用 super 调用父类的构造方法.  
        super(name); 
    } 
} 
class Bird extends Animal { 
    public Bird(String name) { 
      super(name); 
    } 
    public void fly() { 
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿"); 
    } 
} 
public class Test { 
    public static void main(String[] args) { 
        Cat cat = new Cat("小黑"); 
        cat.eat("猫粮"); 
        Bird bird = new Bird("圆圆"); 
        bird.fly(); 
    } 
} 

extends 英文原意指 “扩展”. 而我们所写的类的继承, 也可以理解成基于父类进行代码上的 “扩展”.

例如我们写的 Bird 类, 就是在 Animal 的基础上扩展出了fly方法.

(3)注意

如果我们把 name 改成 private, 那么此时子类就不能访问了

(4)字段和方法访问权限

private: 类内部能访问, 类外部不能访问

默认(也叫包访问权限): 类内部能访问, 同一个包中的类可以访问, 其他类不能访问.

protected: 类内部能访问, 子类和同一个包中的类可以访问, 其他类不能访问.

public : 类内部和类的调用者都能访问

二、多态

首先需要实现多态需要满足一些条件:

1) 继承关系上满足向上转型

2)子类和父类 有同名的覆盖/重写方法

3)通过父类对象的引用去调用这个重写的方法

完成以上三步就会发生动态绑定,动态绑定是多态的基础.

一、向上转型

(1)在刚才的例子中, 我们写了形如下面的代码

Bird bird = new Bird("圆圆"); 

这个代码也可以写成这个样子

Bird bird = new Bird("圆圆"); 
Animal bird2 = bird; 
// 或者写成下面的方式 
Animal bird2 = new Bird("圆圆"); 

此时 bird2 是一个父类 (Animal) 的引用, 指向一个子类 (Bird) 的实例. 这种写法称为 向上转型.

(2)向上转型方法有三种

1)直接赋值

Animal animal = new Dog("圆圆",7);

2)方法的参数,传参是向上转型

public static void funcl(Animal animal){
}
public static void main(String[] args){
  Dog dog = new Dog("圆圆",6);
  func1(dog);
}

3)返回值向上转型

public static Animal func2(){
  Dog dog = new Dog("圆圆",19);
  return dog;
}

二、重写

针对刚才的 eat 方法来说:

子类实现父类的同名方法, 并且参数的类型和个数完全相同, 这种情况称为 覆写/重写/覆盖(Override).

(1)关于重写的注意事项

1)最基本的返回值 参数列表 方法名必须是一样的

2)被重写的方法的访问修饰限定符在子类中要大于等于父类的

3)被private修饰的方法不可以被重写的

4)被static修饰的方法是不可以被重写的

5)被final修饰的方法是不可以被重写的

三、动态绑定

子类和父类中出现同名方法的时候, 再去调用会出现什么情况呢?

对前面的代码稍加修改, 给 Bird 类也加上同名的 eat 方法, 并且在两个 eat 中分别加上不同的日志.

// Animal.java 
public class Animal { 
    protected String name; 
    public Animal(String name) { 
        this.name = name; 
    } 
    public void eat(String food) { 
        System.out.println("我是一只小动物"); 
        System.out.println(this.name + "正在吃" + food); 
    } 
} 
// Bird.java 
public class Bird extends Animal { 
    public Bird(String name) { 
        super(name); 
    } 
    public void eat(String food) { 
        System.out.println("我是一只小鸟"); 
        System.out.println(this.name + "正在吃" + food); 
    } 
} 
// Test.java 
public class Test { 
    public static void main(String[] args) { 
        Animal animal1 = new Animal("圆圆"); 
        animal1.eat("谷子"); 
        Animal animal2 = new Bird("扁扁"); 
        animal2.eat("谷子"); 
    } 
} 
// 执行结果 
我是一只小动物 
圆圆正在吃谷子 
我是一只小鸟 
扁扁正在吃谷子 

此时, 我们发现:

animal1 和 animal2 虽然都是

Animal 类型的引用, 但是 animal1 指向

Bird 类型的实例.

针对 animal1 和 animal2 分别调用 eat 方法, 发现

animal2.eat() 实际调用了子类的方法

四、多态的好处

类调用者对类的使用成本进一步降低.

封装是让类的调用者不需要知道类的实现细节.

多态能让类的调用者连这个类的类型是什么都不必知道, 只需要知道这个对象具有某个方法即可

相关文章
|
2月前
|
算法 Java 程序员
在Java的编程世界里,多态不仅仅是一种代码层面的技术,它是思想的碰撞,是程序员对现实世界复杂性的抽象映射,是对软件设计哲学的深刻领悟。
在Java的编程世界里,多态不仅仅是一种代码层面的技术,它是思想的碰撞,是程序员对现实世界复杂性的抽象映射,是对软件设计哲学的深刻领悟。
60 9
|
20天前
|
Java 编译器
封装,继承,多态【Java面向对象知识回顾①】
本文回顾了Java面向对象编程的三大特性:封装、继承和多态。封装通过将数据和方法结合在类中并隐藏实现细节来保护对象状态,继承允许新类扩展现有类的功能,而多态则允许对象在不同情况下表现出不同的行为,这些特性共同提高了代码的复用性、扩展性和灵活性。
封装,继承,多态【Java面向对象知识回顾①】
|
3天前
|
Java 编译器
在Java中,关于final、static关键字与方法的重写和继承【易错点】
在Java中,关于final、static关键字与方法的重写和继承【易错点】
15 5
|
1天前
|
存储 Java 测试技术
Java零基础-多态详解
【10月更文挑战第1天】Java零基础教学篇,手把手实践教学!
15 1
|
3天前
|
安全 Java 编译器
【一步一步了解Java系列】:重磅多态
【一步一步了解Java系列】:重磅多态
12 3
|
3天前
|
Java 编译器
【一步一步了解Java系列】:子类继承以及代码块的初始化
【一步一步了解Java系列】:子类继承以及代码块的初始化
15 3
|
1月前
|
Java 编译器
Java——类与对象(继承和多态)
本文介绍了面向对象编程中的继承概念,包括如何避免重复代码、构造方法的调用规则、成员变量的访问以及权限修饰符的使用。文中详细解释了继承与组合的区别,并探讨了多态的概念,包括向上转型、向下转型和方法的重写。此外,还讨论了静态绑定和动态绑定的区别,以及多态带来的优势和弊端。
40 9
Java——类与对象(继承和多态)
|
9天前
|
Java
为什么Java不支持多继承
本文讨论了Java不支持多继承的原因,包括避免菱形继承问题、简化编程语言和防止层次膨胀,同时提供了实现多继承效果的替代方案,如实现多接口、使用组合和继承加接口的方式。
11 0
为什么Java不支持多继承
|
22天前
|
Java
Java 多态趣解
在一个阳光明媚的午后,森林中的动物们举办了一场别开生面的音乐会。它们组成了一支乐队,每种动物都有独特的演奏方式。通过多态的魅力,狗、猫和青蛙分别展示了“汪汪”、“喵喵”和“呱呱”的叫声,赢得了观众的阵阵掌声。熊指挥着整个演出,每次调用 `perform()` 方法都能根据不同的动物对象唤起对应的 `makeSound()` 方法,展现了 Java 多态性的强大功能,让整场音乐会既有趣又充满表现力。
|
22天前
|
Java
Java 的继承
在一个森林中,各种动物共存,如狗和猫。为了管理和组织这些动物,我们采用面向对象的方法设计模型。首先创建 `Animal` 超类,包含 `name` 和 `age` 属性及 `makeSound()` 和 `displayInfo()` 方法。接着,通过继承 `Animal` 创建子类 `Dog` 和 `Cat`,重写 `makeSound()` 方法以发出不同的声音。实例化这些子类并使用它们,展示了继承带来的代码重用、扩展性和多态性等优点。这种方式不仅简化了代码,还体现了现实世界的层次结构。