Java面向对象与继承

目录

Java面向对象与继承

实现继承

方法重写

继承中成员变量和成员方法访问的特点

访问成员变量

访问成员方法

访问特点总结

super和this关键字

super关键字

this关键字

Java继承的特点

为父类成员赋值

抽象

继承案例


Java面向对象与继承

实现继承

在Java中,使用extends关键字进行继承,基本格式如下:

class 子类 extends 父类 {

}

例如下面的代码:

// 父类
public class Base {
}

// 子类
public class Derived extends Base{
}

在上面的代码中Base类为父类,Derived类为子类

当子类继承父类时,子类会拥有父类所有的成员,包括私有和公有的成员,但是子类只能使用父类公有的成员,例如下面的代码:

public class Base {
    public String str;
    private int num;
}

此时子类继承Base类时,会拥有成员变量strnum,但是子类只能使用str

方法重写

不同于方法重载,方法重写需要满足函数名相同、返回值(或是被继承类的所有子类)和形参列表相同,并且方法重写的前提是继承,如果子类重写了父类方法,则子类优先访问重写后的父类方法,例如下面的代码

// 父类
public class Base {
    public void base() {
        System.out.println("父类中的方法");
    }
}

// 子类
public class Derived extends Base{
    @Override
    public void base() {
        System.out.println("子类重写父类方法");
    }
}

public class Test {
    public static void main(String[] args) {
        Base base = new Base();
        Derived derived = new Derived();

        base.base(); // 父类访问自己的方法
        derived.base(); // 子类访问重写父类的方法
    }
}

输出结果:
父类中的方法
子类重写父类方法

子类重写父类方法,子类重写的方法权限不可以比父类被重写方法权限低,方法权限一共有四种(访问权限依次降低):

  1. public
  2. protected
  3. 默认(default,不显式写)
  4. private

例如,父类定义的是public的方法,则子类继承的方法不可以是被public以下的权限修饰符修饰,否则属于权限降低

需要注意,重写方法不能对下面的父类方法进行重写:

  1. 父类中的私有方法
  2. 父类中的静态方法
  3. 父类中的构造方法

在Java中,可以使用注解@Override判断该方法是否是重写了父类方法,如果不是,则使用该注解会报错

继承中成员变量和成员方法访问的特点

访问成员变量

当子类继承父类时,子类对象可以访问到父类中的非私有成员变量和自己的成员变量,但是父类对象只能访问父类自己的成员变量,无法访问子类中的成员变量,例如下面的代码:

// 父类
public class Base {
    public String str;
    private int num;
}

// 子类
public class Derived extends Base{
    String newAdded; // 子类新增成员
}

public class Test {
    public static void main(String[] args) {
        Base base = new Base();
        base.str = "父类";
        // base.newAdded; // 父类不能访问子类中新增的成员
        Derived derived = new Derived();
        // 子类可以访问父类的非私有成员,也可以访问子类自己的成员
        derived.str = "子类";
        derived.newAdded = "子类新增成员";
    }
}

如果出现父类的成员变量与子类新增的成员变量重名时,子类依旧访问的自己的成员变量而不是与其重名的父类成员变量,父类已经访问自己的成员变量

// 父类
public class Base {
    public int num = 100;
}

// 子类
public class Derived extends Base{
    public int num = 1000;
}

public class Test {
    public static void main(String[] args) {
        Base base = new Base();
        Derived derived = new Derived();

        System.out.println(base.num);
        System.out.println(derived.num);
    }
}

输出结果:
100
1000

访问成员方法

当子类继承父类时,子类对象可以访问到子类自己的方法,也可以访问到父类方法;父类对象可以访问到自己的方法,也可以通过接收子类对象访问子类重写父类的方法(见多态),例如下面的代码:

// 父类
public class Base {
    public String str;
    private int num;

    public void base() {
        System.out.println("父类中的方法");
    }
}

// 子类
public class Derived extends Base{
    String newAdded; // 子类新增成员

    public void derived() {
        System.out.println("子类方法");
    }
}

public class Test {
    public static void main(String[] args) {
        Base base = new Base();
        Derived derived = new Derived();
        base.base(); // 父类访问自己的方法
        derived.base(); // 子类访问父类的方法
        derived.derived();// 子类访问自己的方法
    }
}

访问特点总结

  • 访问成员变量:关注创建对象时赋值符号的左侧是子类还是父类。如果是父类,则访问的是父类成员变量,如果是子类,则访问的是父类非私有成员和子类自身的成员变量
  • 访问成员方法:关注创建对象时赋值符号的右侧是调用子类构造函数和父类构造函数。如果是父类,则访问的是父类中的成员方法,如果是子类,则访问的是父类中非私有的成员方法、子类重写的父类的方法和子类自身的成员方法

superthis关键字

super关键字

在继承中,默认情况下,子类则访问的是自己的成员,如果此时子类需要访问父类的成员,则需要使用到super关键字

在Java中,super关键字代表父类引用,其作用有以下三种:

  1. 在子类构造方法中访问父类的构造方法
  2. 在子类中访问父类的非私有成员变量
  3. 在子类中访问父类的非私有成员方法

当在子类构造方法中访问父类的构造方法时,一般是用于构造属于父类的成员,而因为父类比子类在创建子类对象时先创建,所以必须写在子类构造方法中的第一行,基本格式如下:

public 子类 {
    super();
    // super(形参); 使用父类中有参构造时使用
}

当子类需要访问父类的成员时,使用下面的格式:

super.父类非私有成员

this关键字

前面在介绍方法时,为了防止方法中出现局部变量与类成员变量重名导致优先访问局部变量的问题,使用this来指代使用类成员变量,下面主要介绍this关键字

this关键字指代当前调用的对象的引用,即哪个对象调用了成员,this就是哪个对象的引用,同super一样,this关键字的作用一共有三种:

  1. 在当前类的一个构造方法中访问当前类的其他构造方法
  2. 在当前类中调用当前类的成员变量
  3. 在当前类中调用当前类的成员方法

当使用this在当前类的一个构造方法中访问当前类的其他构造方法时,需要与super一样,将相关语句放在构造方法的第一行,基本格式同super关键字。但是需要注意,如果当前构造方法中已经有了super调用父类构造方法则不能再写this调用其他构造方法,二者会冲突

当使用this访问当前类的成员时,使用方法同super一样

注意,不能在静态成员方法中使用 this

Java继承的特点

在Java中,子类一次只能继承一个父类,但是父类可以被多个子类继承,并且存在多层继承关系

  • 父类被多个子类继承
// 父类
public class Base {
}

// 子类
public class Derived01 extends Base{
}
public class Derived02 extends Base{
}

在上述代码中Base作为父类有两个子类

  • 多层继承关系
// 父类
public class BaseTop {
}
// 继承自BaseTop
public class Base extends BaseTop{
}
// 继承自Base
public class Derived extends Base{
}

在多层继承关系中,每一个子类都包含其祖先的所有成员

为父类成员赋值

在继承出现后,当子类对象需要为父类成员赋值时,可以使用两种方法:

  1. 子类构造方法中使用super调用父类构造方法
  2. 父类提供相关成员变量的set方法

抽象

有些情况下,父类中的方法并没有实现的意义,此时可以将这种方法修饰为抽象方法,使用abstract关键字,当一个类中定义了抽象方法,则该类也必须被修饰为abstract,对于这种类,称为抽象类。格式如下:

public abstract 类名 {
    public abstract 返回值类型 函数名(形参列表) {
    }
}

抽象类有下面的几个特点:

  1. 抽象类中可以有抽象方法,也可以有非抽象方法
  2. 抽象类不可以实例化出对象
  3. 抽象类的抽象方法必须被子类重写,否则编译报错
  4. 抽象类虽然没有办法实例化出对象,但是依旧可以有对应的成员变量、构造方法和成员方法,对于构造方法来说,是为了子类可以在子类的构造函数初始化父类的成员变量

继承案例

某IT公司有多名员工,按照员工负责的工作不同,进行了部门的划分(研发部、维护部)。

研发部(Developer)根据所需研发的内容不同,又分为 JavaEE工程师 、Android工程师 ;

维护部(Maintainer)根据所需维护的内容不同,又分为 网络维护工程师(Network) 、硬件维护工程师(Hardware) 。

公司的每名员工都有他们自己的员工编号、姓名,并要做它们所负责的工作。

工作内容:

  • JavaEE工程师: 员工号为xxx的 xxx员工,正在研发电商网站
  • Android工程师:员工号为xxx的 xxx员工,正在研发电商的手机客户端软件
  • 网络维护工程师:员工号为xxx的 xxx员工,正在检查网络是否畅通
  • 硬件维护工程师:员工号为xxx的 xxx员工,正在修复电脑主板

请根据描述,完成员工体系中所有类的定义,并指定类之间的继承关系。进行XX工程师类的对象创建,完成工作方法的调用。

此处提供一种思路, Employee作为抽象父类,其他员工均作为子类,重写父类中的 work方法

实现代码如下:

// 父类
package com.epsda.advanced.extends_exercise;

/**
 * ClassName: Employee
 * Description:
 *
 * @author 憨八嘎
 * @version 1.0
 */
public abstract class Employee {
    private String id;
    private String name;
    private String department;

    public Employee(String id, String name, String department) {
        this.id = id;
        this.name = name;
        this.department = department;
    }

    public String getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public abstract void work();
}
// 子类1
public class JavaEE_Engineer extends Employee{
    public JavaEE_Engineer(String id, String name, String department) {
        super(id, name, department);
    }

    @Override
    public void work() {
        System.out.println("员工号为"+getId()+"的"+getDepartment()+"的"+getName()+"员工"+",正在研发电商网站");
    }
}

// 子类2
public class Android_Engineer extends Employee{
    public Android_Engineer(String id, String name, String department) {
        super(id, name, department);
    }

    @Override
    public void work() {
        System.out.println("员工号为"+getId()+"的"+getDepartment()+"的"+getName()+"员工"+",正在研发电商的手机客户端软件");
    }
}

// 子类3
public class Network_Engineer extends Employee{
    public Network_Engineer(String id, String name, String department) {
        super(id, name, department);
    }

    @Override
    public void work() {
        System.out.println("员工号为"+getId()+"的"+getDepartment()+"的"+getName()+"员工"+",正在检查网络是否畅通");
    }
}

// 子类4
public class Hardware_Engineer extends Employee{
    public Hardware_Engineer(String id, String name, String department) {
        super(id, name, department);
    }

    @Override
    public void work() {
        System.out.println("员工号为"+getId()+"的"+getDepartment()+"的"+getName()+"员工"+",正在修复电脑主板");
    }
}
如果考虑将开发的两个部门继承自 Employee,则需要注意,两个部门类不需要重写方法,自然也就定义成 abstract类,直到最后一个作为子类的类重写 work方法即可

  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

怡晗★

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

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

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

打赏作者

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

抵扣说明:

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

余额充值