面向对象——继承

目录

一、继承的基本概念

二、继承的应用

三、使用继承和重写实现子类

1.使用继承定义部门及其子类

2.使用super关键字调用父类成员

3.方法重写

4.方法隐藏

5.Object类

6.实例化子类对象

7.this和super的区别

8.final关键字


一、继承的基本概念

继承中可以解决编程中代码冗余的问题,新类可以在不增加自身代码的情况下,通过从现有类中将继承其属性和方法,来实现充实自身内容,这种现象或行为就称为继承。新类称为子类,现有类称为父类。

Java类中只支持单继承,即一个类只能有一个直接父类。

类与类之间有三种关系,分别是“is a”,“use a”,“has a”,继承表达的是“is a”。

语法规则:

[访问修饰符] class 子类名 extends 父类名{

子类成员变量;

子类成员方法;

}

  • 访问修饰符如果是public,该类在整个项目中可见。
  • 如果不写访问修饰符,该类只在当前包中可见。 

继承的一些基本概念:

  • 子类可以继承父类的非私有属性和方法 ,子类可以使用父类的属性和方法。
  • 子类可以添加父类中没有的属性和方法。
  • 在子类的构造方法中可以通过super关键字调用父类的构造方法,构造不能被继承。
  • Object是所有类的根类,每个类都是它的子类。
  • 只支持单一继承,每个类只有一个直接父类。

二、继承的应用

package method;
//定义一个父类
public class Person { //定义person类
    protected int age;
    protected String name;
    public Person(int age,String name){
        this.age=age;
        this.name=name;
    }
    public  Person(){}
    public void printInfo(){
        System.out.println("name:"+name);
        System.out.println("age:"+age);
    }
}

三、使用继承和重写实现子类

1.使用继承定义部门及其子类

package method;

public class Child  extends Person{
    private String school;
    public Child(String school){
        this.school=school;
    }
    public void printSchool(){
        System.out.println("School:"+school);
    }
}

2.使用super关键字调用父类成员

当需要在子类中调用父类的构造方法时,可以使用super关键字调用。super用在子类中,访问直接父类中被隐藏的内容。super关键字不仅可以访问父类的构造方法,还可以访问父类的成员、父类的普通方法等。

调用父类构造方法:super([实参列表]);

调用父类属性和方法:super.父类的字段名或方法名;

  • super只能出现在子类中
  • 无法通过super访问父类的private成员
  • super用在子类构造函数中时,必须是构造函数中第一行代码。
package method;

public class Child  extends Person{
    private String school;
    public Child(String school,int age,String name){
        super(age, name);
        this.school=school;
    }
    public void printSchool(){
        System.out.println("School:"+school);
    }
}
    class Test{
        public static void main(String[] args) {
            Child c=new Child("Primary school",18,"Jerry");
            c.printInfo();
        }

}

 

3.方法重写

如果从父类中继承的方法不能满足子类的需求,可以在子类中对父类同名方法进行重写(覆盖),以符合子类的需求。

package method;

public class Child  extends Person{
    private String school;
    public Child(String school,int age,String name){
        super(age, name);
        this.school=school;
    }

    @Override
    public void printInfo() {
        super.printInfo();
        System.out.println("school:"+school);
    }
}
    class Test{
        public static void main(String[] args) {
            Child c=new Child("Primary school",18,"Jerry");
            c.printInfo();
        }

}

面向对象——继承_第1张图片

方法重写必须满足以下要求:

  • 在继承关系中
  • 重写方法与被重写方法必须同名
  •  重写方法与被重写方法必须同参
  • 重写方法与被重写方法必须同返回值
  • 重写方法不能缩小被重写方法的访问权限
  • 不能用子类的非静态方法重写父类的静态方法,否则会编译报错
  • 不能重写父类中的最终方法
  • 不能用子类的静态方法重写父类的实例方法。

方法重载和方法重写的区别:

方法重载是在一个类中定义多个同名但是参数不同的方法,而方法重写是在子类中重写父类的方法,方法名和参数都相同。方法重载是编译时多态,方法重写是运行时多态。

4.方法隐藏

父类和子类拥有相同名字的属性或方法时,父类的同名的属性或方法形式上不见了,实际还是存在的。(方法隐藏只有一种形式,就是父类和子类存在签名相同的静态方法)。

package method;

public class Person { //定义person类
    public static int age=20;
    public static String name="父类";
    public static double weight=45.5;
    public static String key="kfm";
    public static void print(){
        System.out.println("Parent.print()");
    }


    public void printInfo(){
        System.out.println("name="+name+",age="+age+",weight="+weight+",key="+key);
    }
}
package method;

public class Child  extends Person{
    public String name="子类";
    public static int age=12;
    public static final double weight=23;
    public static String key="kfm2";

    public static void print(){
        System.out.println("Child.print()");
    }
    public void printInfo(){
        System.out.println("name="+name+",age="+age+",weight="+weight+",key="+key);
    }

}
package method;

public class Test {
    public static void main(String[] args) {
        Child child=new Child();
        child.print();
        child.printInfo();

        Person child1=new Child();
        child1.print();
        child1.printInfo();
    }
}

面向对象——继承_第2张图片  调用静态方法时,看等号左边,调用实例方法时,看等号右边。

隐藏是对于静态方法和成员变量(静态变量和实例变量)而言的 :

  • 当发生隐藏时,声明对象是什么类,就调用对应类的方法。
  • 属性只能被隐藏,不能被覆盖
  • 变量可以交叉隐藏:子类的实例变量/静态变量可以隐藏父类的实例变量/静态变量。
  • 不能用子类的静态方法隐藏父类的非静态方法,否则编译报错。

5.Object类

Object类是所有类的父类。所有的Java类都直接或间接的继承了java.lang.Object类。在定义一个类时,没有使用extends关键字,也就是没有显式的继承某个类,那么这个类直接继承Object类。

String toString() 返回当前对象本身的有关信息,返回字符串对象
boolean equals(Object) 比较两个对象是否是同一个对象,若是,返回true
Object clone() 生成当前对象的一个副本,并返回
Class getClass() 获取类结构信息,返回class对象
int hashCode() 返回对象的哈希码值
重写 equals 要求
* 对 null 返回 false
* 自反性:x.equals(x) 返回true
* 对称性: x.equals(y) 的值 和 y.equals(x) 的值一样
* 传递性: x.equals(y) 为 true, y.equals(z) 为 true, 此时 x.equals(z) 为 true
* 一致性: x.equals(y) 多次调用结果一致
* 重写了 equals 就要重写 hashCode

6.实例化子类对象

子类在实例化时,会首先执行其父类的构造方法,然后才执行子类的构造方法。子类继承父类时,其构造方法调用规则如下:

  • 如果子类的构造方法中没有通过super显式调用父类的有参构造方法,也没有通过this显式的调用自身其他的构造方法,系统会默认调用父类无参的构造方法。
  • 如果父类的构造方法中通过super([实参列表])显式的调用了父类的有参构造方法,那么将执行父类对应的构造方法,而不执行父类无参构造方法。
  • 如果子类的构造方法中通过this显式得调用了自身的其他构造方法,遵循以上两条规则。
package method;

public class Person { //定义person类
    private String name;
    public Person(){
        System.out.println("execute Person()");
    }
    public Person(String name){
        this.name=name;
        System.out.println("execute Person(name)");
    }
}
class Student1 extends Person{
    String school;
    public Student1(){
        System.out.println("execute Student()");
    }
    public Student1(String name,String school){
        super(name);
        this.school=school;
        System.out.println("execute Student(name,school)");
    }
}
class PostGraduate extends Student1{
    String guide;

    public PostGraduate() {
        System.out.println("execute PostGraduate()");
    }

    public PostGraduate(String name, String school, String guide) {
        super(name, school);
        this.guide = guide;
        System.out.println("execute PostGraduate(name,school,guide)");
    }
}
package method;

public class PersonTest {
    public static void main(String[] args) {
        PostGraduate postGraduate=null;
        postGraduate=new PostGraduate();
        System.out.println();
        postGraduate=new PostGraduate("喵星人","开发喵学院","大佬");
    }
}

面向对象——继承_第3张图片 

7.this和super的区别

this和super都是关键字,用于引用当前对象或父类对象。

调用方法

this访问本类中的方法,包括从父类继承的方法。

super访问父类的方法。

调用构造方法

this([参数列表])表示调用本类的构造方法,必须放在构造方法的首行。

super([参数列表])表示调用父类构造,必须放在子类构造方法首行,如果表示调用父类的无参构造,super()可省略。

调用字段

this.字段:调用的是当前的字段,包括从父类继承的字段。

super.字段:调用的是父类中的字段。

使用

this在实例方法中可以使用,在static方法中不可以使用,每个类都有this。

super在实例方法中可以使用,在static方法中不可以使用,只能在子类中使用。

8.final关键字

 用于修饰变量、方法和类,表示它们是不可改变或不可继承的。

  • final修饰变量:final修饰的变量称为常量,一旦被初始化,就无法再被修改。常量必须在声明时或者在构造函数中初始化。常量的命名一般采用大写字母和下划线。
package method;

public class Person { //定义person类
    final static double PI=3.14159264674645;

    public static void main(String[] args) {
        System.out.println("PI:"+Person.PI);
    }
}
  •  final修饰方法:final修饰的方法称为不可覆盖方法,子类无法重写该方法。
  • final修饰类:final修饰的类称为不可继承类,表示该类不能被其他类继承。 

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