9.继承

继承

继承概述

面向对象三大特征之一, 可以使得子类具有父类的属性和方法, 还可以在子类中重新定义, 追加属性和方法.

继承格式:

  • public class 子类名 extends 父类名{}

范例

  • public class child extends parent{}

  • child: 子类,也称为派生类

  • parent: 父类,也称为基类, 超类

例子

demo

package classInherit;

public class Demo {
    public static void main(String[] args) {
        // 创建对象
        parent p = new parent();
        p.show();

        child c = new child();
        c.method();
        c.show();  // 子类调用父类的show方法
    }
}

child

package classInherit;

public class child extends parent {  // 继承父类
    public void method() {
        System.out.println("子类method方法");
    }
}

parent

package classInherit;

public class parent {
    public void show() {
        System.out.println("父类show方法");
    }
}

继承的好处和弊端

好处

  • 提高了代码的复用性(多个类相同的成员可以放到同一个类中)
  • 提高了代码的维护性(如果方法的代码需要修改,修改一处即可)

弊端

  • 类的耦合性增强, 当父类发生变化时子类实现也不得不跟随变化,削弱了子类的独立性

使用子类的场景

  • 继承体现的关系: is

注意:

  • 如果子类想要访问父类中的属性, 那么父类中的属性必须定义为public.
  • 子类和父类中有相同的属性或方法,会优先使用子类的属性或方法.

继承中变量访问特点

在子类中访问一个变量

  1. 子类局部范围查找
  2. 子类成员范围找
  3. 父类成员范围找

如果都没有会报错

super关键字

super关键字和this关键字用法相似

  • this: 代表本类对象的引用
  • super: 代表父类存储空间的表示(可以理解为父类对象的引用)
关键字 访问成员变量 访问构造方法 访问成员方法
this this.成员变量: 访问本类成员变量 this(...): 访问本类的构造方法 this.成员方法(...): 访问本类成员方法
super super.成员变量: 访问父类成员变量 super(...): 访问父类构造方法 super.成员方法(...): 访问父类成员方法

例子

package classInherit;

public class child extends parent {  // 继承父类
    // 身高
    public int height = 175;
    public int age = 30;
    public void show() {
        int age = 40;
        System.out.println("子类method方法");
        System.out.println(this.height);
        // 访问age, 先局部,后子类,最后父类
        System.out.println(age);

        System.out.println("子类成员变量: " + this.age);
        System.out.println("父类成员变量: " + super.age);
    }
}

构造方法访问特点

子类中所有的构造方法默认都会访问父类中无参的构造方法

  • 子类会继承父类的数据,可能还会使用父类的数据, 所以, 子类初始化之前, 一定要先完成父类数据的初始化
  • 每一个子类构造方法的第一条语句默认都是: super(),

如果父类中没有无参改造方法, 只有带参构造方法, 子类构造方法直接会报错

  • 可以在子类中通过super手动调用父类的带参构造方法来避免.
  • 在父类中提供一个无参构造方法(推荐)

Parent

package classInherit.initialMethod;

public class Parent {
    /*
    public Parent() {
        System.out.println("Parent中无参构造方法");
    }
    */
    public Parent(int age) {
        System.out.println("Parent中带参构造方法");
    }
}

child

package classInherit.initialMethod;

public class Child extends Parent {  // 继承父类
    public Child() {
        super(20);
        System.out.println("Child中无参构造方法");
    }
    public Child(int age) {
        super(20);
        System.out.println("Child中带参构造方法");
    }
}

Demo

package classInherit.initialMethod;

public class Demo {
    public static void main(String[] args) {
        // 创建对象
        Child c = new Child();
        System.out.println("-----------手动分割----------");
        Child c2 = new Child(20);
    }
}

成员方法访问特点

通过子类对象访问一个方法

  • 子类成员范围查找
  • 父类成员范围查找
  • 如果都没有会报错,(不考虑父亲的父亲)

parent

package classInherit.memberMethod;

public class Parent {
    public void show() {
        System.out.println("Parent中show方法被调用");
    }
}

child

package classInherit.memberMethod;

public class Child extends Parent {  // 继承父类
    public void method() {
        System.out.println("Child中method方法被调用");
    }
    public void show() {
        super.show();
        System.out.println("Child中show方法被调用");
    }
}

demo

package classInherit.memberMethod;

public class Demo {
    public static void main(String[] args) {
        // 创建对象
        Child c = new Child();
        c.method();
        c.show();
        // c.test();  // 报错
    }
}

方法重写

子类中出现了和父类中一模一样的方法申明, 内容但是方法内容不一致

  • 当子类需要父类的功能, 而功能主体子类有自己特有内容时, 可以重写父类中的方法, 这样, 既沿袭了父类的功能, 又定义了子类特有的内容

@Override

  • 是一个注解
  • 可以帮助我们检查重写方法声明的正确性

Phone

package classInherit.methodRewrite;

public class Phone {
    public void call(String name) {
        System.out.println("给" + name + "打电话");
    }
}

NewPhone

package classInherit.methodRewrite;
/*
    新手机
 */
public class NewPhone extends Phone {
    /*
    public void call(String name) {
        System.out.println("开启视频功能!");
        // System.out.println("给" + name + "打电话");
        super.call(name);
    }
     */

    @Override
    public void call(String name) {
        System.out.println("开启视频功能!");
        // System.out.println("给" + name + "打电话");
        super.call(name);
    }
}

Demo

package classInherit.methodRewrite;

public class Demo {
    public static void main(String[] args) {
        // 创建对象,调用方法
        Phone p = new Phone();
        p.call("ryxiong");

        System.out.println("-------");

        NewPhone p2 = new NewPhone();
        p2.call("ryxiong");
    }
}

注意事项:

  • 父类的私有方法, 子类无法访问, 所以也无法重写

  • 子类方法访问权限不能更低(public > 默认 > 私有)

继承的注意事项

java中只支持单继承, 不支持多继承

java类中支持多层继承

GrandFather

package classInherit.inheritNotes;

public class GrandFather {
    public void drink() {
        System.out.println("爷爷爱喝酒");
    }
}

Father

package classInherit.inheritNotes;

public class Father extends GrandFather {
    public void sing() {
        System.out.println("爸爸爱唱歌");
    }
}

Mother

package classInherit.inheritNotes;

public class Mother {
    public void dance() {
        System.out.println("妈妈爱跳舞");
    }
}

Son

package classInherit.inheritNotes;

public class Son extends Father {

}

案例

Person

package classInherit.inheritPractice;

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

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = 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;
    }
}

Teacher

package classInherit.inheritPractice;

public class Teacher extends Person {
    public Teacher() {
    }

    public Teacher(String name, int age) {
        super(name, age);
    }

    public void teach() {
        System.out.println("用爱成就每一位学员");
    }
}

Demo

package classInherit.inheritPractice;
/*
    测试类
 */

public class Demo {
    public static void main(String[] args) {
        // 创建老师类
        Teacher t1 = new Teacher();
        t1.setName("林青霞");
        t1.setAge(30);
        System.out.println(t1.getName() + "," + t1.getAge());
        t1.teach();

        // 带参构造方法
        Teacher t2 = new Teacher("风清扬", 33);
        System.out.println(t2.getName() + "," + t2.getAge());
        t2.teach();
    }
}

本质上就是文件夹

作用: 对类进行分类管理

包的定义格式

  • 格式: package 包名; 多级包用.分开
  • 范例: package com.itheima;

带包的java类编译和执行

  • 手动建包
    • 按照以前格式编译java文件: javac HelloWorld.java
    • 手动创建包, 创建文件夹com/itheima/
    • 将class文件放到文件夹com/itheima/下
    • 带包执行 java com.itheima.HelloWorld
  • 自动建包
    • Javac -d . HelloWrold.java
    • java com.itheima.HelloWorld

修饰符

修饰符权限

修饰符 同一类中 同一个包中子类无关类 不同包的子类 不同包的无关系
private
默认
protected
public

pkgs.Parent

package modifier.pkgs;

public class Parent {
    private void show1() {
        System.out.println("private");
    }

    void show2() {
        System.out.println("default");
    }

    protected void show3() {
        System.out.println("protected");
    }

    public void show4() {
        System.out.println("public");
    }

    public static void main(String[] args) {
        // 创建父类对象,测试哪些方法可以使用
        Parent p = new Parent();
        p.show1();
        p.show2();
        p.show3();
        p.show4();
    }
}

pkgs.Child

package modifier.pkgs;

public class Child extends Parent {
    public static void main(String[] args) {
        // 创建Child对象,测试哪些方法可以使用
        Child c = new Child();
        c.show2();
        c.show3();
        c.show4();
    }
}

pkgs.Demo

package modifier.pkgs;

public class Demo {
    public static void main(String[] args) {
        // 创建Parent类对象, 测试看看哪些可以使用
        Parent p = new Parent();
        p.show2();
        p.show3();
        p.show4();
    }
}

test.Child

package modifier.test;

import modifier.pkgs.Parent;

public class Child extends Parent {
    public static void main(String[] args) {
        // 创建Child对象,测试看看哪些方法可以使用
        Child c = new Child();
        c.show3();
        c.show4();
    }
}

test.Demo

package modifier.test;

public class Demo {
    public static void main(String[] args) {
        // 创建Child对象,测试看看哪些方法可以使用
        Child c = new Child();
        c.show4();
    }
}

final修饰符

表示最终, 可以修饰成员方法, 成员变量, 类

final特点:

  • 修饰方法: 最终方法, 不能被重写
  • 修饰变量: 变量为常量, 不能再次被赋值
  • 修饰类: 该类为最终类, 不能被继承

parent

package modifier.finalDemo;

// 被final修饰的类,不能被继承
/*
public final class Parent {
    public final void method() {
        System.out.println("Parent method");
    }
}
*/

public class Parent {
    public final void method() {
        System.out.println("Parent method");
    }
}

child

package modifier.finalDemo;

public class Child extends Parent {
    public final int age = 20; // 被final修饰的值不能被修改
    public void show() {
        // age = 100;
        System.out.println(age);
    }

    /*
    @Override  // 被final修饰的方法不能重写
    public void method() {
        System.out.println("Child Method");
    }
     */
}

Demo

package modifier.finalDemo;

public class Demo {
    public static void main(String[] args) {
        Child c = new Child();
        c.method();
        c.show();
    }
}

final修饰局部变量

  • 修饰基本类型: final修饰指的是基本类型的数据值不能发生改变

  • 修饰引用类型: final修饰值得是引用类型地址值不能发生改变, 但是地址里面的内容可以发生改变.

Student

package modifier.finalDemo;

public class Student {
    public int age = 20;
}

FinalDemo

package modifier.finalDemo;

public class FinalDemo {
    public static void main(String[] args) {
        // final修饰基本类型变量
        final int age = 20;
        // age = 100;
        System.out.println(age);

        // final修饰引用类型变量
        final Student s = new Student();
        s.age = 100;  // s是指一个地址, 内容可以变, 但是地址不能变
        System.out.println(s.age);

        // s = new Student();  // final修饰后, 地址值不能改变

    }
}

Static修饰符

static 关键字是静态的意思, 可以修饰成员方法, 成员变量

static 修饰的特点

  • 被类的所有对象共享: 这也是我们判断是否使用静态关键字的条件

  • 可以通过类名调用, 也可以使用对象名调用, 推荐使用类名

Student

package modifier.staticDemo;

public class Student {
    public String name;
    public int age;
//    public String university;
    public static String university;  // 所有对象能够共享的属性, 用static修饰

    public void show() {
        System.out.println(name + "," + age + "," + university);
    }
}

StaticDemo

package modifier.staticDemo;

public class StaticDemo {
    public static void main(String[] args) {
        // static属性直接通过类来赋值
        Student.university = "传智大学";
        Student s1 = new Student();
        s1.name = "林青霞";
        s1.age = 30;
        // s1.university = "传智大学";
        s1.show();

        Student s2 = new Student();
        s2.name = "风清扬";
        s2.age = 33;
        s2.show();
    }
}

static访问特点

非静态成员方法

  • 能访问静态的成员变量
  • 能访问非静态的成员变量
  • 能访问静态的成员方法
  • 能访问非静态的成员方法

静态成员方法

  • 能访问静态的成员变量
  • 能访问讲台成员方法

静态成员只能访问静态成员

Student1

package modifier.staticDemo;

public class Student1 {
    // 非静态成员变量
    private String name = "林青霞";
    // 静态成员变量
    private static String university = "传智大学";

    // 非静态成员变量
    public void show1() {
    }

    // 非静态成员方法
    public void show2() {
        System.out.println(name);
        System.out.println(university);
        show1();
        show3();
    }

    // 静态成员方法
    public static void show3() {

    }

    // 静态成员方法
    public  static void show4() {
        // System.out.println(name);  // 无法访问
        System.out.println(university);
        // show1();  // 无法访问
        show3();
    }
}

posted @ 2020-10-28 11:55  ryxiong728  阅读(103)  评论(0编辑  收藏  举报