关于java:一文打尽Java继承的相关问题

8次阅读

共计 3933 个字符,预计需要花费 10 分钟才能阅读完成。

相干文章:

  1. 《面向对象再探索》:介绍了面向对象的基本概念
  2. 《详解 Java 的对象创立》:介绍了对象的创立、结构器的应用

在《面向对象再探索》这篇文章中曾经抽象的介绍过继承的概念了,上面就来具体介绍继承的应用等相干问题。

1. 引入例子

Animal 类和 Dog 类例子,下文都会围绕该例开展。

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

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

    public Animal() {}

    public void say() {System.out.println("我是" + name + ",往年" + age + "岁了");
    }

    //getters and setters ...
}
public class Dog extends Animal {

    private String address;

    public Dog(String name, int age, String address) {super(name, age);
        this.address = address;
    }

    public Dog() {}

    public void say() {System.out.println("我叫" + super.getName() + ",往年" + super.getAge() + "岁了,家住" + address + ",汪汪汪...");
    }

    public void watchDoor() {System.out.println("我在" + address +"看门...");
    }

    //getters and setters ...
}

Dog类继承 Animal 类,Animal类有 nameage 属性和 say() 办法,Dog类减少了 address 属性和 watchDoor() 办法。

2. 概念介绍

在现实生活中有许多继承的例子,比方“子承父业”、“继承父母财产”、“继承某人意志”等,这些都是在强调一个体失去另一个体的货色,他们之间存在“继承关系”。

在 Java 中,继承是类和类之间的关系。在《面向对象再探索》这篇文章中举了动物 Animal 类和狗 Dog 类、猫 Cat 类、兔子 Rabbit 类的例子并写了代码,这里间接拿来用不再列出,请移步此文章。

咱们能够说狗、猫、兔子是动物,但不能够说动物是狗、猫、兔子。动物广泛有眼睛、耳朵等属性,有跑、吃、叫等行为。狗显然也具备这些属性和行为,然而狗也具备一些它特有的属性和行为,比方灵活的鼻子、看门等。

在这个例子中,Animal类是父类,Dog类、Cat类、Rabbit类是子类。子类和父类存在继承关系,能够说:子类“是”父类,该关系是继承的一个显著特色。

上面是对于继承的几个 Q &A:

Q1: 什么时候须要用到继承?

A1: 集体认为可从以下两点登程:

  1. 面向对象语言是对事实世界的形象,所谓“万物皆对象”,那么咱们在理论开发中的类必定都是与事实世界的实物绝对应的,所以看实物之间的关系有没有继承关系。
  2. 当有若干类有大量反复的属性和办法,那么就能够思考应用继承,将这些反复的属性和办法抽成父类。

Q2: 怎么应用继承?

A2: 子类应用 extends 关键字继承父类,也只有应用了该关键字后,才存在继承关系及“父子类”:

public class Animal {// 父类
    // 属性和办法
}
public class Dog extends Animal {// 子类继承父类
    // 属性和办法    
}

Q3: 在具体开发中,是先编写父类,而后扩大出子类,还是先编写子类,而后形象出父类?

A3: 集体认为不能一概而论。如果你的零碎设计十分好,能够先写好父类,而后扩大子类。如果你没设计好,或者考虑不周,那么前期可能会呈现许多类有反复代码,这时候能够思考抽取父类。

Q4: 父类和子类在内容上有什么区别?

A4: 通常,咱们将更通用的一些属性和办法放到父类中,比方狗、猫、兔子都具备的属性和办法会办法动物类中。子类中是更加特地的属性和办法,比方狗的看门行为、猫的抓老鼠行为。因为子类继承了父类,所以子类中只须要编写和父类的不同之处。

所以,子类往往会比父类领有更加丰盛的属性和办法。

Q5: 子类继承的父类的哪些货色?

A5: 这里先给出论断,下文再具体介绍。子类继承了父类的 非公有 private成员变量、办法、嵌套类,子类不继承父类的结构器,然而子类能够调用父类的结构器。

Q6: Java 中能够继承多个类吗?

A6: Java 中的继承是单继承,只能继承一个类。

3. 具体应用

3.1. 子类重写父类的办法

有时子类从父类继承失去的办法不肯定实用,这时子类能够重写父类的办法。如 Dog 类重写了其父类的 say() 办法。

留神要和 重载 加以辨别。

简略来说,重写波及到的是两个类的同名办法,重载波及到的是一个类的同名办法。对于重载介绍请移步这里。

3.2. 子类新增属性和办法

后面提到:子类是对父类的扩大,子类内容比父类更加丰盛。所以通常子类都会有本人的属性和办法,比方 Dog 类的 address 属性和 watchDoor() 办法。

3.3. 子类如何应用父类的公有成员?

子类不继承父类的公有成员 ,然而如果父类有能拜访其公有成员变量的publicprotected的办法(比方 getter 办法),那么子类能够通过继承这些办法来应用父类的公有办法(Java 官网教程)。

上面用下面的代码例子解释:

Animal类有公有成员变量、和私有办法 say()say() 间接拜访本类的公有成员变量,没故障!

public class Animal {
    private String name;
    private int age;
    
    public void say() {System.out.println("我是" + name + ",往年" + age + "岁了");
    }
    // 其余代码...
}

当初 Dog 类继承 Anima

public class Dog extends Animal {

    private String address;
    
    public void say() {//name 和 age 报红
        System.out.println("我叫" + name + ",往年" + age + "岁了,家住" + address + ",汪汪汪...");
    }
    
    // 其余代码...
}

请留神 Dog 类的 say() 办法,间接拜访了 nameage属性,如果子类继承了父类的公有成员,那么这样写是没问题的,但事实是 nameage报红了,阐明子类没有继承父类的公有成员。

尽管子类没有继承父类的公有成员,然而咱们能够通过父类的私有办法应用其公有成员变量,代码改变如下:

public class Dog extends Animal {

    private String address;
    
    public void say() {System.out.println("我叫" + super.getName() + ",往年" + super.getAge() + "岁了,家住" + address + ",汪汪汪...");
    }
    
    // 其余代码...
}

应用 super.xxx() 能够调用父类的办法,因为 getName() 是父类私有办法,且能拜访父类的公有成员变量 name,所以子类调用getName() 办法能够应用 name 变量。

3.4. 子类如何对父类的公有成员赋值?

子类没有继承父类的公有成员变量,当然不能间接赋值。通常有两种办法:调用父类的私有 setter 办法或调用父类的结构器。实质上还是子类通过应用父类提供的私有办法(setter 或结构器)应用其公有成员变量。

3.4.1. 应用 setter 办法:

public class Dog extends Animal {

    private String address;

    public void setName(String name) {super.setName(name); // 留神 super
    }

    public void setAge(int age) {super.setAge(age);
    }

    public void say() {System.out.println("我叫" + super.getName() + ",往年" + super.getAge() + "岁了,家住" + address + ",汪汪汪...");
    }

    // 其余代码...
}

Dog类的两个 setter 办法调用了 Animal 类的两个 setter 办法,因为子类的 setter 办法名和父类的 setter 办法名获得一样(重写了),所以肯定要应用 super 关键字加以辨别,否则就成递归了。

3.4.2. 调用父类的结构器:

public class Dog extends Animal {

    private String address;

    public Dog(String name, int age, String address) {super(name, age); // 调用父类结构器
        this.address = address;
    }

    public Dog() {}


    public void say() {System.out.println("我叫" + super.getName() + ",往年" + super.getAge() + "岁了,家住" + address + ",汪汪汪...");
    }
    
    // 其余代码...
}
public class Animal {
    private String name;
    private int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // 其余代码...
} 

子类应用 super() 语句调用父类结构器,该语句必须是子类结构器的第一行代码。

如果子类结构器没有显式调用父类结构器,则会默认调用父类的无参结构器。所以如果父类没有无参结构器,而子类又没有显式调用父类的其余结构器,则会报错。

4. 对于我

如有谬误,还请斧正。

正文完
 0