7.java-继承

继承

一,类继承的定义与作用

1.定义与作用

继承就是赠与获取的关系,直接获取资源,增强功能等

Java中的继承指的是子类获取了父类提供的属性或方法,从而大大实现代码的复用,并增强了子类的功能,同时提高了代码的可维护性。

2.使用方式,子类使用extends关键字实现继承

二,继承的作用

创建父类,声明通用属性与方法>子类使用extends继承父类,继承父类公共方法或属性,创建自己特有属性与方法>创建对象,调用父类的方法或子类的方法实现功能

说明:继承的同时别忘了使用封装

案例解析:

/**
 * @创建父类,以便子类继承并共享父类通用的方法
 * @请使用封装
 */
public class Animal {
    private int id;
    private String type;
    private String aname;
    private String sex;
    private double value;

    public Animal() {
    }

    public Animal(int id, String type, String aname, String sex, double value) {
        this.id = id;
        this.type = type;
        this.aname = aname;
        this.sex = sex;
        this.value = value;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getAname() {
        return aname;
    }

    public void setAname(String aname) {
        this.aname = aname;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public double getValue() {
        return value;
    }

    public void setValue(double value) {
        this.value = value;
    }
}

小结:

1.常见的父类与子类

Persion人类>Employee,Manager

user用户类>Admin管理员,Employee

Animal>Dog,Cat,Fish

Plant植物>Flower,Grass

2.Java的继承是单继承,可以链式继承

3.子类只能继承父类公共的属性与公共方法,但不能继承父类的构造器

4.子类可以有自己的属性与自己的方法

5.无论是父类或子类都要有无参构造器,有参构造器建议创建

6.继承中要使用封装

三,super关键字与this关键字

所有的类都有一个成为Object的父类,又称为超类,基类,所有的类都直接或间接继承Object类

1.super关键字,作用有两个

(1)一个是代表父类的构造器,并调用父类的构造器来初始化父类成员变量(成员属性),必须在子类构造器的第一行。

(2)另一个作用是代表父类的对象,可以来调用父类的所有非私有方法或非私有属性

2.this关键字:两个作用

(1)代表当前类的构造器,并调用当前类的构造器来初始化当前类的成员变量,必须在当前类的第一行

(2)代表当前类的当前对象,可以用来调用当前类的所有非私有的方法和属性

案例解析

import sun.util.resources.LocaleData;

/**
 * 定义父类
 *
 */
public class Student {
    private int id;
    private String name;
    private String gender;
    //出生日期,LocaleDate
    private LocaleData birth;
    private long moblie;

    public Student() {
    }
    //有参构造器创建对象的同时只能赋初值
    public Student(int id, String name, String gender, LocaleData birth, long moblie) {
        //调用最大的父类Object的无参构造器
        this.id = id;
        this.name = name;
        this.gender = gender;
        this.birth = birth;
        this.moblie = moblie;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public LocaleData getBirth() {
        return birth;
    }

    public void setBirth(LocaleData birth) {
        this.birth = birth;
    }

    public long getMoblie() {
        return moblie;
    }

    public void setMoblie(long moblie) {
        this.moblie = moblie;
    }
    //  更多方法
    //返回所有属性的值,主要用于测试程序toString
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", birth=" + birth +
                ", moblie=" + moblie +
                '}';
    }
}
import sun.util.resources.LocaleData;

/**
 * 定义子类
 *
 */
public class Boy extends Student{
    //特有属性
    private String face;
    //构造器
    public Boy(){}

    public Boy(int id, String name, String gender, LocaleData birth, long moblie, String face) {
        //this/super不能同时使用
        //调用了父类的构造器
        super(id, name, gender, birth, moblie);
        //初始化子类特有属性
        this.face = face;
    }
    //提供Set/get

    public String getFace() {
        return face;
    }

    public void setFace(String face) {
        this.face = face;
    }
}

四,方法重写(覆盖)的作用

在子类中,创建了一个与父类中名称、返回值类型、参数列表都完全相同的方法,只是方法体的功能实现不同,这种方式被称为方法重写(override),或者叫方法覆盖

方法重写(覆盖Override)作用:

指的是子类继承了父类并调用了父类非私有的方法,并对此方法进行了扩展,从而增强了子类的功能,这种机制称为方法的覆盖Override,又称为方法重写,并为多态的实现提供了前置条件。

方法重写的要求

父类的成员方法只能被它的子类重写,即不能继承一个方法,就不能重写这个方法;

被final修饰的方法不能被重写;

被static修饰的方法不能被重写,但可以再次声明;

构造方法不能被重写;

子类和父类在同一个包中时,子类可以重写父类中除了被private和final修饰的其他所有方法;

子类和父类不在同一个包中时,子类只能重写父类被public和protected修饰的非final方法;

重写的方法建议使用@Override注解来标识。

方法重写注意事项
  • 方法签名要相同:重写的方法和被重写的方法,在方法名、参数上都要相同;
  • 返回值类型一致:JDK 1.5之前重写方法的返回值类型必须一样,但之后的Java版本放宽了限制,返回值类型必须小于或等于父类方法的返回值类型
  • 访问修饰符要更宽泛:子类重写父类的方法时,子类方法中的访问修饰符不能比父类中的更严格(public>protected>default>private)。比如父类方法的修饰符是protected,则子类的同名方法其修饰符可以是protected或public,但不能是默认的或private;
  • 声明的异常类型要一致:重写的方法一定不能抛出新的检査异常,或者比被重写方法声明更宽泛的检査型异常。例如,父类的方法声明了IOException,重写该方法时就不能抛出Exception,只能拋出IOException或其子类异常。但可以抛出非检査异常

方法重写时可以带有@Ovriride关键词。当重写的方法签名不一致时,会有编译错误的提示,否则方法签名不一致时不会有错误提示,会被当做一个新的方法来处理。

当子类对象调用重写的方法时,默认执行的是子类的方法,而不是父类中被重写的方法。如果我们想要调用父类中被重写的方法,则可以使用“super.方法名”的形式。

如果子类的功能是在父类的基础之上进行的额外扩展,我们可以使用super关键字调用父类的同名方法,然后再进行自己的额外扩展!

如果子类的实现和父类完全不一样,可以不调用super!

方法重写时,子类可以对父类的同名方法进行扩展实现,方法体的内容可以和父类中的实现不一样。

@Override注解

@Override是一个用来修饰被重新的方法的注解,只能用在被重新的方法上,不能用在其它的地方。该注解可以强制子类必须重写父类的方法或者接口中的方法,主要是告诉编译器检查重写的方法是否和父类中定义的一致。如果重写的方法签名不一致,会提示编译错误。如果方法签名不一致,则不会有错误提示,会被当做一个新的方法来处理。通过这样的机制,就可以避免程序员出现一些低级的错误。

重写与重载的区别

其实方法重写Override和方法重载Overload的最大不同,在于方法签名的不同。如果同一个类中的多个方法签名不同,就是方法重载Overload,重载出的方法是一个新方法。如果父子类之间的多个方法签名相同,且返回值也相同,就是方法重写Override。

重载的特点

  • 方法重载要求方法同名不同参(参数类型、个数、顺序);
  • 重载的方法与返回值、访问修饰符无关;
  • 重载的方法发生在同一个类中,是在一个类中创建多个同名的方法。

重写的特点

  • 重写的方法发生在父子类中,需要有继承关系;
  • 父类的成员方法只能被它的子类重写,即不能继承一个方法,就不能重写这个方法;
  • 被final修饰的方法不能被重写;
  • 被static修饰的方法不能被重写,但可以再次声明;
  • 构造方法不能被重写;
  • 子类和父类在同一个包中时,子类可以重写父类中除了被private和final修饰的其他所有方法;
  • 子类和父类不在同一个包中时,子类只能重写父类被public和protected修饰的非final方法;
  • 方法重写时可以使用@Override注解;
  • 方法签名要相同;
  • 返回值类型一致;
  • 访问修饰符要更宽泛;
  • 声明的异常类型要一致。

子类构造器的特点:

子类的全部构造器,都会先调用父类的构造器,再执行自己

补充:

  • 任意类的构造器其中,可以通过this(…)去调用该类的其他构造器的。
  • this(…)和super(…)都只能放在构造器的第一行,因此,有了this(…)就不能写super(…)了,返之亦然

开闭原则:对功能拓展做开放,对修改代码做闭合

你可能感兴趣的:(java,开发语言)