Java 继承与多态

Java 继承与多态,第1张

Java 继承与多态 继承 (1)子类继承父类,相当于拥有了父类的成员变量和成员方法

​ I.子类可以重写父类的方法:

​ 1、方法名称要一样

​ 2、返回值数据类型要一样

​ 3、所使用的参数列表要一样,也就是形参必须一直

​ 4、访问修饰符只能越来越开放,不能越来越封闭(比如从private到public)

重写父类的方法:

public class A {
    public void show(String name){
        System.out.println("父类的show方法");
    }
}
public class B extends A{
    public void show(String name){
        System.out.println("子类的show方法");
    }
}

这里B类继承了A类,重写了A类的show方法(方法名一直,返回值一直,形参一直)

public class Demo{
    public static void main(String[] args) {
        B b = new B();
        b.show("parameter");
    }
}

所以使用B的show方法,那么就会输出

子类的show方法

使用父类的方法:

如果上面的代码修改一下子类show方法的形参,改为整形呢?

public class B extends A{
    public void show(int paramenter){
        System.out.println("子类的show方法");
    }
}

继续使用上面的Demo代码

public class Demo{
    public static void main(String[] args) {
        B b = new B();
        b.show("parameter");
    }
}

就会输出:

父类的show方法

因为子类并没有重写父类的show方法,只是创建了一个新的show方法,形参为整形,所以使用了父类的show方法。

(2)构造方法的继承

​ 创建子类对象的时候,会默认调用父类的无参构造方法:


public class A {
    public A(){
        System.out.println("调用了父类的无参构造方法");
    }
}
//A的子类
public class B extends A{
    public B(){
        System.out.println("调用了子类的无参构造方法");
    }
}
//测试类
public class Demo{
    public static void main(String[] args) {
        B b = new B();
    }
}

输出结果就是:

调用了父类的无参构造方法
调用了子类的无参构造方法

对super和this进行一次复习~下面代码的执行结果是什么呢?


public class A {
    public A(){
        this(123);
        System.out.println("调用了父类的无参构造方法");
    }
    public A(int parameter){
        System.out.println("调用了父类的有参构造方法");
    }
    public void show(){
        System.out.println("调用了父类的show方法");
    }
}
//A的子类
public class B extends A{
    public B(){
        this(123);
        System.out.println("调用了子类的无参构造方法");
    }
    public B(int parameter){
        System.out.println("调用了子类的有参构造方法");
        super.show();
    }
}
//测试类
public class Demo{
    public static void main(String[] args) {
        B b = new B();
    }
}

我们再巩固一下这个知识点,先执行父类的无参构造方法,然后执行子类的无参构造方法。往下拉对一下答案哦

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

调用了父类的有参构造方法
调用了父类的无参构造方法
调用了子类的有参构造方法
调用了父类的show方法
调用了子类的无参构造方法

​ 因为我们在父类的无参构造方法里面,通过this关键字,调用了父类的有参构造方法,所以先执行的是父类的有参构造,然后调用结束,回到无参构造方法这里,输出了父类的无参构造方法。然后父类的无参构造方法执行结束了,就到子类的无参构造方法。子类的无参构造方法也是通过this关键字,调用了子类的有参构造方法,输出了子类的有参构造方法,然后再通过super关键字,调用了父类的show方法,然后执行完毕,再回到子类的无参构造方法继续执行,所以在这段代码里面,子类的无参是最后输出的。

(3)继承有单继承和多重继承

​ I.单继承是指一个子类只能由一个父类(如果一个类没有继承父类,那么它的默认父类就是Object类)。

​ II.多重继承是指子类继承的父类可以还有父类的父类,比如 C extends B,B extends A,就是B继承A,C也继承了B,相当于C继承了B和A

​ 举个例子:

public class A {
    public void show(A a){
        System.out.println("A and A");
    }
}
public class B extends A{
    public void show(A o){
        System.out.println("B and A");
    }
    public void show(B o){
        System.out.println("B and B");
    }
}
public class C extends B{
    public void show(C o){
        System.out.println("C and C");
    }
}

然后我们分别创建C的对象,调用三个show方法来查看

		C c = new C();
        c.show(new A());
        c.show(new B());
        c.show(new C());

因为C里面没有形参为A的show方法,所以先到父类B里面查找,刚好父类B类里面重写了B父类A的show方法,所以调用的是B里面形参为A的show方法,如果B里面没有重写形参为A的show方法,那么就会到B的父类A里面查找有没有形参为A的show方法,如果有,就调用该方法。

这段show的运行结果是:

B and A
B and B
C and C
多态

先来做个简单的科普:

Father object = new Son();

​ 父类引用指向子类对象,其实是 该对象object,数据类型是Father(父类),它只能调用A里面的成员变量和成员方法,那为什么是通过实例化Son(new Son();)来创建呢?

这样可以通过子类重写父类的方法,实现调用子类Son的方法,但是对象object只能使用Father里面有的成员变量和成员方法。

(1)父类引用指向子类对象

​ 有以下代码:

public class A {
    
}
//A的子类
public class B extends A{

}
//测试类
public class Demo{
    public static void main(String[] args) {
        A b = new B();
    }
}

这就是典型的父类引用指向子类对象,这里的父类就是A,引用了 它的子类B。

(2)通过多态创建的对象,只能使用父类的成员属性和成员方法

​ 我们在父类引用指向之类对象中,创建了一个实例化对象 b,它的属性是B类的,但是它的数据结构是A类的。也就是说,b只能用A里面有的成员属性和方法。

先看不是多态创建的对象:

public class A {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
//A的子类
public class B extends A{
    //B继承了A,所以B有A的所有成员方法和成员变量
    public void check(){
        System.out.println(getName()+",年龄是"+getAge());
    }
}
//测试类
public class Demo{
    public static void main(String[] args) {
        B b = new B();
        b.setName("十三");
        b.setAge(18);
        b.check();
    }
}

输出结果是

十三,年龄是18

​ 这就是一个基本的继承,子类继承父类的所有成员属性和成员方法。

再看看通过多态创建的对象:

public class A {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
//A的子类
public class B extends A{
    //B继承了A,所以B有A的所有成员方法和成员变量
    public void check(){
        System.out.println(getName()+",年龄是"+getAge());
    }
}
//测试类
public class Demo{
    public static void main(String[] args) {
        A b = new B();
        b.setName("十三");
        b.setAge(18);
        b.check();
    }
}

​ 你如果自己写代码,你会发现b.check();这里报错了。

会提示:

Cannot resolve method 'check' in 'A'

​ 就是在A中找不到check()方法。

​ 因为是通过多态创建的对象b,它只有A里面的成员属性和成员方法,也就说只能用A里面有的东西。

​ 那么我们可能会疑惑,如果只能用A里面的成员属性和成员方法,那么我们为什么要给它实例化B呢( new B(); )?

(3)子类重写父类方法

​ 如果在子类中重写了父类的方法,那么通过多态创建的对象,在调用父类的被子类重写了的方法的时候,会调用子类重写了父类的这个方法。

比如:

public class A {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    public void check(){
        System.out.println(name);
    }
}
//A的子类
public class B extends A{
    //B继承了A,所以B有A的所有成员方法和成员变量
    public void check(){
        System.out.println(getName()+",年龄是"+getAge());
    }
}
//测试类
public class Demo{
    public static void main(String[] args) {
        A b = new B();
        b.setName("十三");
        b.setAge(18);
        b.check();
    }
}

​ 这时候check()方法就没有报错了,因为A类有check方法,但是它是通过实例化B( new B(); )来得到的对象,所以如果B里面重写了check的话,调用check就会调用B里面的check();

​ 至于为什么要这样做?涉及到设计模式耦合性的问题,到总结那里大概过一下多态的优点即可。

(4)类型转换

​ 子类对象可以当作父类对象来用

​ 父类对象不可以当作子类对象来用

​ 如果父类引用指向子类对象,那么该对象可以通过强制转换成子类对象来使用,如:

public class A {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    public void check(){
        System.out.println(name);
    }
}
//A的子类
public class B extends A{
    //B继承了A,所以B有A的所有成员方法和成员变量
    public void check(){
        System.out.println(getName()+",年龄是"+getAge());
    }
}
//测试类
public class Demo{
    public static void main(String[] args) {
        A b = new B();
        b = (B) b;//这样就回到了继承那边的知识点,子类可以调用父类所有的成员变量和方法~
        b.setName("十三");
        b.setAge(18);
        b.check();
    }
}
(5)总结

​ 如果看完了继承和多态还是觉得绕的话,那么记住如果有用到方法,那么就看=右边的实例对象,如果要用到属性,那么就用=左边

​ 也就是 Father object = new Son();

​ 如果用到了方法,就到Son()里面去找,如果用到了属性,那么就到Father里面找。

​ 多态的必要条件:

​ I.继承

​ II.重写(子类继承父类之后重写父类的方法)

​ III.父类引用指向子类对象

Father object = new Son();

多态的优点:

  • 消除类型之间的耦合关系
  • 可替换性
  • 可扩充性
  • 接口性
  • 灵活性
  • 简化性
继承与多态简易面试题

巩固一下知识点!~

public class A {
    public void show(A object){
        System.out.println("A and A");
    }
    public void show(D object){
        System.out.println("A and D");
    }
}

public class B extends A{
    public void show(B object){
        System.out.println("B and B");
    }
    public void show(A object){
        System.out.println("B and A");
    }
}

public class C extends B{

}

public class D extends B{

}

public class Demo{
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new B();
        B b = new B();
        C c = new C();
        D d = new D();
        System.out.print("1:");
        a1.show(b);
        System.out.print("2:");
        a1.show(c);
        System.out.print("3:");
        a1.show(d);
        System.out.print("4:");
        a2.show(b);
        System.out.print("5:");
        a2.show(c);
        System.out.print("6:");
        b.show(d);
        System.out.print("7:");
        b.show(b);
        System.out.print("8:");
        b.show(c);
        System.out.print("9:");
        b.show(d);
    }
}

问,1-9分别会输出什么?(自己答完可以跑一遍这个程序得到答案)

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/731382.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-27
下一篇 2022-04-27

发表评论

登录后才能评论

评论列表(0条)

保存