继承与多态(1)

简介: 继承与多态(1)

1、继承


面对对象的三大特征:封装性、继承性、 多态性

继承是多态的前提,如果没有继承,就没有多态

在继承的关系中,“子类就是父类”。也就是说,子类可以被当做父类看待。

例如:父类是员工,子类是讲师,那么“讲师就是一个员工”。关系:is-a。

定义父类的格式:(一个普通的类定义)

public class 父类名称{

//…

定义子类的格式:

public class 子类名称 extends 父类名称{

//…


微信图片_20221009120414.png

代码示例:



/

//员工类
public class Employee {
    public void method(){
        System.out.println("方法执行");
    }
}
//讲师类(讲师是员工)
public class Teacher extends Employee {
}
public class Demo01Extends {
    public static void main(String[] args) {
        //创建一个子类对象
        Teacher teacher = new Teacher();
        //Teacher类当中虽然什么都没写,但是会继承来自父类的method方法
        teacher.method();
    }
}


/

1.1继承中成员变量的访问特点


在父子类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式:


1.直接通过子类对象访问成员变量:

 等号左边是谁,就优先用谁,没有则向上找


2.简接通过成员方法访问成文变量:

 该方法属于谁,就优先用谁,没有则向上找


1.2 区分子类方法中重名的三种


  • 局部变量: 直接写
  • 本类的成员变量: this.成员变量名
  • 父类的成员变量: super.成员变量名

代码示例:

//父类
public class Fu {
    int num = 10;
}
1
//子类
public class Zi extends Fu {
    int num = 20;
    public void method(){
        int num = 30;
        System.out.println(num);// 30局部变量
        System.out.println(this.num);//20 本类的成员变量
        System.out.println(super.num);//10 父类的成员变量
    }
}
public class Demo02ExtendsField {
        public static void main(String[] args) {
        Zi zi = new Zi();
        zi.method();
        }
}

1.3继承中构造方法的访问特点


  1. 子类构造方法当中有一个默认隐含的“super()”调用,所以一定是先调用父类的构造,后执行子类的构造
  2. 子类构造可以通过super关键字来调用父类重载构造。
  3. super的父类调用,必须是子类构造方法的第一个语句,不能一个子类构造调用多次super构造
  4. 子类必须调用父类构造方法,不写则赠送super():写了则用写的指定super调用,super只能有一个,还必须是第一个。


1.4 super关键字的三种用法


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


1.5 this关键字的三种用法


  1. 在本类的成员方法中,访问本类的成员变量。
  2. 在本类的成员方法中,访问本来的另一个成员方法。
  3. 在本类的构造方法中,访问本类的另一个构造方法。

注意:super和this关键字不能同时使用


super和this关键字在内存中的图解如下图

微信图片_20221009121257.png


1.6 java继承的三个特点


java语言是单继承的。一个类的直接父类只有一个。

java语言可以多级继承。

一个子类的直接父类是唯一的,但是一个父类可以拥有多个子类。


2、抽象类


2.1 抽象类的概念


抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束。

抽象类:抽象方法所在的类,必须是抽象类才行,在class之前写上abstract即可。


2.2抽象方法是抽象类的使用


不能直接创建new抽象类对象。

必须用一个子类来继承抽象父类.

子类必须覆盖重写抽象父类当中所有的抽象方法。

创建子类对象使用。

注:覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号


代码示例:



//

public class DemoMain {
    public static void main(String[] args) {
        cat cat = new cat();
        cat.eat();
    }
}
//动物父类
public abstract class Animal {
    public abstract void eat();
}


/


/

//猫子类
public class cat extends Animal {
    @Override
    public void eat(){
        System.out.println("猫吃鱼");
    }
}


2.3抽象方法和抽象类的注意事项


抽象类不能创建对象,如果创建,编译无法通过而报错,只能创建其抽象子类的对象

抽象类中,可以有构造方法,是提供子类创建对象时,初始化父类成员使用。

抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错,除非子类也是抽象类。


3、接口


3.1 接口的概念


接口,是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么

接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法

(JDK 9)。

接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并

不是类,而是另外一种引用数据类型。


3.2 定义格式:


public interface 接口名称 {

// 抽象方法:使用 abstract 关键字修饰,可以省略,没有方法体。该方法供子类实现使用。

// 默认方法:使用 default 修饰,不可省略,供子类调用或者子类重写。

// 静态方法: 使用 static 修饰,供接口直接调用。

// 私有方法:使用 private 修饰,供接口中的默认方法或者静态方法调用。

}


注意事项:

1、接口当中的抽象方法,修饰必须是两个固定的关键字:public abstract

2、 这两个关键字修饰符,可以选择性省略。


3.3 接口的使用步骤


接口不能直接使用,必须有一个“实现类”来“实现”该接口。

接口的实现类必须覆盖重写(实现)接口中所有抽象方法。

实现:去掉abstract关键字,加上方法体大括号。

创建实现类对象,进行使用。

注意事项:如果实现类并没有覆盖重写所有抽象方法,那么这个实现类自己就必须是抽象类。


3.3.1抽象方法


使用 abstract 关键字修饰,可以省略,没有方法体。该方法供子类实现使用。接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次。

代码示例:


//定义接口
public interface MyInterfaceAbstract {
    //这是一个抽象方法
    public abstract void methodAbs1();
    //这也是一个抽象方法
    abstract void  methodAbs2();
    //这也是抽象方法
    public void methodAbs3();
    //这也是抽象方法
    void methodAbs4();
}
//定义实现类
public class MyInterfaceAbstractImpl implements MyInterfaceAbstract{
    @Override
    public void methodAbs1() {
        System.out.println("这是第一个方法");
    }
    @Override
    public void methodAbs2() {
        System.out.println("这是第二个方法");
    }
    @Override
    public void methodAbs3() {
        System.out.println("这是第三个方法");
    }
    @Override
    public void methodAbs4() {
        System.out.println("这是第四个方法");
    }
}



/

public class Demo01Interface {
    public static void main(String[] args) {
        MyInterfaceAbstractImpl impl = new MyInterfaceAbstractImpl();
        impl.methodAbs1();
        impl.methodAbs2();
    }
}


3.3.2默认方法


使用 default 修饰,不可省略,供子类调用或者子类重写。接口中,有多个默认方法时,实现类都可继承使用。如果默认方法有重名的,必须重写一次。

代码示例:



/

//定义接口
public interface MyInterfaceDefault {
    //这是一个抽象方法
    public abstract void methodAbs();
    //新添加一个抽象方法
//    public  abstract void methodAbs2();
    //新添加的方法,改成默认方法
    public default void methodDefault(){
        System.out.println("这是新添加的默认方法");
    }
}


//定义实现类
public class MyInterfaceDefaultA implements MyInterfaceDefault {
    @Override
    public void methodAbs() {
        System.out.println("实现抽象方法,AAA");
    }
}


public class MyInterface {
    public static void main(String[] args) {
        //创建实现类对象
        MyInterfaceDefaultA a = new MyInterfaceDefaultA();
        //调用抽象方法,实现运行的是右侧实现类
        a.methodAbs();
        //调用默认方法,如果实现类当中没有,会向上找接口的
        a.methodDefault();
    }
}


3.3.3静态方法


使用 static 修饰,供接口直接调用。接口中,存在同名的静态方法并不会冲突,原因是只能通过各自接口名访问静态方法。

注意事项:不能通过接口实现类的对象来调用接口当中的静态方法。

正确用法:通过接口名称,直接调用其中的静态方法

格式:

接口名称.静态方法名称(参数);


3.3.4私有方法


使用 private 修饰,供接口中的默认方法或者静态方法调用。


3.4 接口中的常量定义与使用


  • 接口中,无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用public static final修饰。
  • 接口中,没有构造方法,不能创建对象。
  • 接口中,没有静态代码块

格式:

public static final 数据类型 常量名称 = 数据值;

注意:


  1. 一旦使用final关键字进行修饰,说明不可改变。
  2. 接口中的常量,必须进行赋值,不能不赋值。
  3. 接口中常量的名称,使用完全大写的字母,用下划线进行分隔。(推荐)


相关文章
|
6月前
|
C#
初识继承和多态
初识继承和多态
|
6月前
|
存储 设计模式 编译器
【C++】继承和多态常见的问题
【C++】继承和多态常见的问题
|
6月前
|
安全 Java 编译器
继承与多态
继承与多态
|
6月前
面向对象编程:类、对象、继承与多态
面向对象编程:类、对象、继承与多态
39 0
|
6月前
|
C++
C++继承、多继承及菱形继承
C++继承、多继承及菱形继承
|
编译器 程序员 C++
【C++】继承和多态
【C++】继承和多态
437 3
|
编译器
【多态-动态绑定-向上转型-抽象类】
【多态-动态绑定-向上转型-抽象类】
46 0
|
编译器 C++
C++类和对象-继承&多态
C++类和对象-继承&多态
75 0
|
Java
类的继承多态
类的继承多态
78 0
总结继承和多态的一些问题
本人学习了多态和继承后的一些问题,解答出来并总结,有些是容易搞混的概念。
总结继承和多态的一些问题