Java的面向对象与继承(类extends继承&&接口implements继承)

面向对象的继承含义

面向对象的三大特征:封装性、继承性和多态性。
继承是多态的前提,如果没有继承、就没有多态。
举例:
继承说明图
继承关系中,”子类就是一个父类“,也就是说子类也可以当作父类来看。
定义父类的格式:(一个普通的类定义)
public class 父类名称{
//成员函数和成员变量
}
定义子类的格式:(一个普通的类定义)
public class 子类名称 extends 父类名称{
//成员函数和成员变量
}
重点原则

【1】成员变量和成员方法重名,访问有两种方式:

在父子类的继承关系中,如果成员变量重名,则创建子类对象时,访问有两种方式:
【直接】通过子类对象访问成员变量:等号左边是谁,就优先用谁,没有就向上找。
【间接】通过成员方法可以访问成员变量:该方法属于谁,就优先用谁,没有再向上找
举例:

父类:
package cn.itcast.day01.demo05;
import java.lang.reflect.Method;
public class Fu {
    int numFu=10;
    int num=100;
    public void  methodFu(){
       System.out.println(num);
    }
}
子类
package cn.itcast.day01.demo05;
public class Zi extends Fu{
    int numZi=20;
    int num=200;
    public void  methodZi(){
        System.out.println(num);
    }
}
kage cn.itcast.day01.demo05;
public class ExtendsField {
    public static void main(String[] args) {
        System.out.println("************成员变量**************");
        Fu fu=new Fu();
        System.out.println(fu.numFu);//10有,自己的】
        System.out.println(fu.num);//相同变量【num】【自己】100
        Zi zi=new Zi();
        System.out.println(zi.numZi);//20
        System.out.println(zi.num);//相同变量【num】【自己】200
        System.out.println(zi.num);//200
        //System.out.println(zi.ccc);//都没有,访问错误
        System.out.println("************成员方法**************");
        zi.methodZi();//200【属于Zi,结果为Zi】
        fu.methodFu();//100【属于F,结果为Fu】
        zi.methodFu();//100【属于Fu,结果为Fu】
    }
}

【2】同名变量的不同的使用方法

  • 局部变量:直接写成员变量名
  • 本类的成员变量:this.成员变量
  • 父类的成员变量:super.成员变量名
父类:
package cn.itcast.day01.demo05;
import java.lang.reflect.Method;
public class Fu {
    int num=10;
}
子类:
package cn.itcast.day01.demo05;
public class Zi extends Fu{
    int numZi=20;
    public void  method(){
    int i=30;
        System.out.println(num);//30
        System.out.println(this.num);//20
        System.out.println(super.num);//10
    }
}i
主函数:
kage cn.itcast.day01.demo05;
public class ExtendsField {
    public static void main(String[] args) {
        zi.method();//30,20,10
    }
}

【3】同名成员方法的不同使用方法

在父子类的继承关系中,创建子类对象,访问成员方法的规则:
创建的对象是谁,就优先用谁,如果没有则向上找。
注意事项
无论是成员函数还是成员变量,如果没有都是向上找父类,绝对不会向下找子类。

父类:
package cn.itcast.day01.demo05;
import java.lang.reflect.Method;
public class Fu {
    public void  methodFu(){
       System.out.println("父类方法调用");
    }
     public void  method(){
       System.out.println("子类方法调用");
    }
}
子类:
package cn.itcast.day01.demo05;
public class Zi extends Fu{
    int numZi=20;
    public void  method(){
     public void  method(){
       System.out.println("子类方法调用");
    }
    public void  methodZi(){
       System.out.println("子类方法调用");
    }
}
主函数:
kage cn.itcast.day01.demo05;
public class ExtendsField {
    public static void main(String[] args) {
        //创建的是new子类对象,所以优先用子类方法。
        zi.method();//子类方法调用
        //
         zi.methodZi();//子类方法调用
         zi.methodFu();//父类方法调用
    }
}

方法的重写(Override)

概念
在继承关系中,方法的名称一样,参数列表也一样。
注意事项

  • 必须保证父子类之间方法的名称相同,参数列表也相同。
  • @overdide:写在方法的前面,用来检测是不是有效的覆盖重写。这个注解就算不写也是正确的方法。
  • 子类方法的返回值必须【小于等于】父类方法的返回值范围。object类是所有类的公共最高父类,String是object的子类。
  • 子类方法的权限必须【大于等于】父类方法的权限修饰符。public>protected>(default)留空>private
    什么时候使用
    对父类中一个方法的功能进行扩展和增加时,需要创建一个子类对原有的方法进行复写。
    举例:
父类:
package cn.itcast.day01.demo05;
public class Phone {
    public  void call(){
        System.out.println("打电话");
    }
    public  void sent(){
        System.out.println("发短信");
    }
    public  void show(){
        System.out.println("显示号码");
    }
}
package cn.itcast.day01.demo05;
public class NewPhone extends Phone {
    @Override
    public  void show(){
        super.show();
        System.out.println("显示地区");
        System.out.println("显示姓名");

    }
}
主函数
package cn.itcast.day01.demo05;
public class PhoneDemo {
    public static void main(String[] args) {
        Phone p=new Phone();
        p.call();
        p.sent();
        p.show();
        System.out.println("***************************");
        NewPhone np=new NewPhone();
        np.show();
        np.call();
        np.sent();
    }
}

运行结果:

打电话
发短信
显示号码
***************************
显示号码
显示地区
显示姓名
打电话
发短信

父子构造方法的访问特点

  • 子类构造方法中有一个默认隐含的super()调用;所以一定是先调用的父类构造,后执行的子类构造。
  • 子类构造可以通过supper关键字来调用父类重载构造。
  • super的父类构造调用,必须是【子类构造方法】的【第一个】语句。不能在一个子类构造中多次调用super()构造.
    举例:
父类:
package cn.itcast.day01.demo05;
public class GouzaoFu {
    public GouzaoFu(){
        System.out.println("父类的无参构造");
    }
    public GouzaoFu(int num){
        System.out.println("父类的有参构造");
    }
}

子类:
package cn.itcast.day01.demo05;
public class GouzaoZi extends GouzaoFu{
    public GouzaoZi(){
        //super();默认是父类的无参构造【其一】
        super(20);//可以调用父类的有参构造【其一】
        System.out.println("子类的无参构造");
    }
    public void method(){
        //super.();//只能在子类的构造方法中才可以使用

    }

}
主函数:
package cn.itcast.day01.demo05;
public class Gouzaodemo {
    public static void main(String[] args) {
        GouzaoZi zi=new GouzaoZi();
    }
}

运行结果:

父类的有参构造
子类的无参构造

super关键字的使用方法

  • 在子类的成员方法中,访问父类的成员变量。在子类中, super.【父类】成员变量。
  • 在子类的成员方法中,访问父类的成员方法。在子类中,super.【父类】成员方法();
  • 在子类的构造方法中,访问父类的构造方法。super()//super(参数)。
    举例:
package cn.itcast.day01.demo05;
public class GouzaoZi extends GouzaoFu{
    public GouzaoZi(){
        //super();默认是父类的无参构造【其一】
        super(20);//可以调用父类的有参构造【其一】
        System.out.println("子类的无参构造");
    }
    public void method(){
        super.method();
        System.out.println(super.num);
        //super.();//只能在子类的构造方法中才可以使用
    }
    public void methodZi(){
        System.out.println(super.num);
        //super.();//只能在子类的构造方法中才可以使用
    }

this关键字的使用方法

  • 1.在本类的成员方法中,访问本类的成员变量。
  • 2.在本类的成员方法中,访问本类的另一个成员方法。
  • 3.在本类的构造方法中,访问本类的另一个构造方法。
  • 4.第三种方法中要注意:A—>this(…)调用也必须是构造方法的第一个语句,唯一的一个。B—>super和this两个种构造调用,不能同时使用。
    举例:
package cn.itcast.day01.demo05;
public class Zi extends Fu{
    int numZi=20;
    int num=200;
    public Zi(){
      this(123);//本类的无参构造调用有参构造【构造方法的重载构造】
    }
    public Zi(int n){
        System.out.println("子类的有参构造"+n);
    }
    public void  methodZi(){
        int num=2000;
        System.out.println(num);//局部变量2000
        System.out.println(this.num);//本类的成员变量200
        System.out.println(super.num);//父类的成员变量10
        this.show();
    }
    public void show(){
     System.out.println("AAA");

    }
}

Super和This的内存情况

在这里插入图片描述

接口的含义

接口是一种公共的规范标准。只要符合规范标准,就可以大家通用。例如,USB接口,电源插座。

接口的定义格式

publid interface 接口名称{
//接口内容
}
备注:编译生成的字节码文件仍然是:.Java---->.class文件

接口的内容

如果是Java7,那么接口内容为:

  1. 常量
  2. 抽象方法
    如果是Java8,还有内容:
  3. 默认方法
  4. 静态方法
    如果Java9,还有内容:
  5. 私有方法
    接口的使用步骤:
    1.接口不能直接使用,必须有一个“实现类”来【实现】该接口
    格式:
    继承:public class 类名称 extends 父类名称{//内容}
    接口:public class 实现类名称 implements 接口名称{
    //内容
    }
    2.接口的实现类必须覆盖重写(实现)接口所有的抽象方法。
    实现:去掉abstract关键字,加上方法体大括号。
    3.创建实现类的对象,进行使用。
    注意事项:
    如果实现类并没有覆盖重写接口中所有的抽象方法,那么这个实现类自己就必须是抽象类。

抽象方法

格式:
public abstract 返回值类型 方法体名称(参数列表);无方法体

抽象类:
package cn.itcast.day01.demo07;
public interface MyInterfaceAbs {
    public abstract void abs1();
    public  void abs2();
    abstract void abs3();
     void abs4();

}
实现类:
package cn.itcast.day01.demo07;

public class MyInterfaceAbsImpl implements MyInterfaceAbs   {
    @Override
    public void abs1() {System.out.println("抽象方法一实现");

    }

    @Override
    public void abs2() {System.out.println("抽象方法二实现");

    }

    @Override
    public void abs3() {System.out.println("抽象方法三实现");

    }

    @Override
    public void abs4() {System.out.println("抽象方法四实现");

    }
}
主函数:
package cn.itcast.day01.demo07;
public class InterfaceDemo {
    public static void main(String[] args) {
        MyInterfaceAbsImpl impl=new MyInterfaceAbsImpl();
        impl.abs1();impl.abs2();
        impl.abs3();impl.abs4();
    }
}
运行结果:
抽象方法一实现
抽象方法二实现
抽象方法三实现
抽象方法四实现

默认方法

格式:
public default 返回值类型 方法体名称(参数列表){
//方法体
}

  1. 接口的默认方法,可以通过接口实现类对象,直接调用。//找不到就向接口找该方法。
  2. 接口的默认方法,也可以被接口实现类进行覆盖重写。//用实现类自己的方法
接口内添加新的默认方法,可以保持实现类内容不变,而且不会出错。
package cn.itcast.day01.demo07;
public interface MyInterfaceAbs {
    public abstract void abs1();
    public  void abs2();
    abstract void abs3();
     void abs4();
     //public abstract void method2();//实现类会有问题,实现类只实现了四个抽象方法
     public default void  method1(){
         System.out.println("这是新添加的默认方法");
     }
}
主函数:实现类直接调用默认方法。
package cn.itcast.day01.demo07;
public class InterfaceDemo {
    public static void main(String[] args) {
        MyInterfaceAbsImpl impl=new MyInterfaceAbsImpl();
        impl.abs1();impl.abs2();
        impl.abs3();impl.abs4();
        impl.defaultmethod1();
    }
}
运行结果:
抽象方法一实现
抽象方法二实现
抽象方法三实现
抽象方法四实现
这是新添加的默认方法

静态方法

格式:
public static 返回值类型 方法体名称(参数列表){
//方法体
}//类名称.静态方法
//接口名称.静态方法

接口类:静态方法的添加,实现类没动,直接接口名.静态方法实现。
package cn.itcast.day01.demo07;
public interface MyInterfaceAbs {
    public abstract void abs1();
    public  void abs2();
    abstract void abs3();
     void abs4();
     //public abstract void method2();//实现类会有问题,实现类只实现了四个抽象方法
     public default void  defaultmethod1(){
         System.out.println("这是新添加的默认方法");
     }
     public static void staticmethod(){
         System.out.println("这是新添加的静态方法");
     }
}
实现类:
package cn.itcast.day01.demo07;
public class MyInterfaceAbsImpl implements MyInterfaceAbs   {
    @Override
    public void abs1() {System.out.println("抽象方法一实现");

    }
    @Override
    public void abs2() {System.out.println("抽象方法二实现");

    }
    @Override
    public void abs3() {System.out.println("抽象方法三实现");
    }

    @Override
    public void abs4() {System.out.println("抽象方法四实现");
    }
}
主函数:直接接口名.静态方法。
package cn.itcast.day01.demo07;
public class InterfaceDemo {
    public static void main(String[] args) {
        MyInterfaceAbsImpl impl=new MyInterfaceAbsImpl();
        impl.abs1();impl.abs2();
        impl.abs3();impl.abs4();
        impl.defaultmethod1();
        MyInterfaceAbs.staticmethod();
    }
}

抽象方法一实现
抽象方法二实现
抽象方法三实现
抽象方法四实现
这是新添加的默认方法
这是新添加的静态方法

私有方法

问题描述:我们需要抽取一个共有方法,来解决两个默认方法之间代码重复的问题。
但是这个共有方法不应该让实现类使用,应该进行私有化。
java 9开始,接口当中允许定义私有方法。

package cn.itcast.day01.demo07;
public interface MyInterFacePrivate {
    public default void methodDefault1(){
        System.out.println("默认方法1");
        comment();
    }
    public default void methodDefault2(){
        System.out.println("默认方法2");
        comment();
    }
   public default void comment(){
        System.out.println("AAA");
        System.out.println("BBB");
        System.out.println("CCC");
    }
}

  1. 普通私有方法,解决多个默认方法之间的代码重复问题;格式:private 返回值类型 方法名称(参数列表){ //方法体}
  2. 静态私有方法,解决多个静态方法之间的代码重复问题;格式:private static 返回值类型 方法名称(参数列表){ //方法体}
    举例:
package cn.itcast.day01.demo07;
public interface MyInterFacePrivate {
    public default void methodDefault1(){
        System.out.println("默认方法1");
        comment();
    }
    public default void methodDefault2(){
        System.out.println("默认方法2");
        comment();
    }
    private void comment(){
        System.out.println("AAA");
        System.out.println("BBB");
        System.out.println("CCC");
    }
    public static void methodDefault1(){
        System.out.println("默认方法1");
        comment();
    }
    public static void methodDefault2(){
        System.out.println("默认方法2");
        comment();
    }
    private void comment2(){
        System.out.println("DDD");
        System.out.println("EEE");
        System.out.println("TTT");
    }
}

成员变量

接口当中也可以定义”成员变量“,但是必须使用 public static final三个关键字进行修饰。
从效果上看,就是接口的【常量】
格式:
piblic static final 数据类型 常量名称(完全大写)=数据值;
备注:
一旦使用了final关键字进行修饰,将永远改变不了。
注意事项:

  • 接口当中的常量,可以【省略】public static final,注意:不写也照样是这样
  • 接口当中的常量,必须【赋值】。
  • 接口当中的常量名称,使用完全【大写字母】,用【下划线】进行分隔(推荐)
    使用方法:
    接口名称.常量。

接口使用的注意事项

  • 没有静态代码块或者构造方法的。
    格式:
    static{//只执行一次,初始化类中的初始变量,优先于构造函数。
    }
    public MyInterfaceA(){}
  • 一个类的直接父类只有一个,但是一个类可以同时实现多个接口。
    格式:
    public class MyInterfaceImpl implements MyinterfaceA,MyinterfaceA{
    //覆盖重写所有的抽象方法
    }
  • 如果实现类,在实现多个接口,但是多个抽象接口的【抽象方法】重名,只需要重写一个重名抽象方法就可以。
  • 如果实现类没有覆盖重写所有的接口当中的抽象方法,那么实现类就必须是一个抽象类。
  • 如果实现类实现的多个接口当中,存在的重复【默认方法】,那么实现类一定要对冲突的默认方法进行覆盖重写。
  • 一个类如果直接父类当中的方法,和接口当中的默认方法,产生了冲突,优先用父类的方法。
接口A
package cn.itcast.day01.demo07;
public interface MyInterfaceA {
    public abstract void mathod1();
    public abstract void abs();
    public default void defaultmethod(){
        System.out.println("接口A的默认方法");
    }
}

接口B
package cn.itcast.day01.demo07;
public interface  MyInterfaceB {
    public abstract void mathod2();
    public abstract void abs();
    public default void defaultmethod(){
        System.out.println("接口B的默认方法");
    }

}
实现类:
package cn.itcast.day01.demo07;

public class MyInterfaceABimpl implements MyInterfaceA,MyInterfaceB{
    @Override
    public void mathod1() {
        System.out.println("覆盖重写了1方法");
    }
    @Override
    public void mathod2() {
        System.out.println("覆盖重写了2方法");
    }

    @Override
    public void abs() {
        System.out.println("覆盖重写了A和B接口都有的【抽象方法】abs");
    }

    @Override
    public void defaultmethod() {
        System.out.println("对多个接口当中冲突的【默认方法】进行了覆盖重写");
    }
}

类和接口之间的关系

  1. 类和类之间是单继承的。直接父类只有一个。
  2. 类和接口之间是多实现的。一个类可以实现多个接口。
  3. 接口和接口之间是多继承的。
    注意事项
    多个父接口当中的【抽象方法】如果重复了,没关系。【抽象方法没有方法体】
    多个父接口当中的【默认方法]如果重复了,有关系。那么子接口必须进行默认方法的覆盖重写,而且带着【default】关键字。
接口A
package cn.itcast.day01.demo07;
public interface MyInterfaceA {
    public abstract void mathod1();
    public abstract void abs();A
    public default void defaultmethod(){
        System.out.println("接口A的默认方法");
    }
}

接口B
package cn.itcast.day01.demo07;
public interface C {
    public abstract void mathod2();
    public abstract void abs();
     public default void defaultmethod(){
        System.out.println("接口B的默认方法");
    }
   
}

接口C:拥有四种方法,继承了三个,自己还有一个
package cn.itcast.day01.demo07;
public interface MyInterfaceC extends MyInterfaceA, MyInterfaceB {
    public abstract void mathod();
  
}

实现类:有四个重写方法,继承了子接口。
package cn.itcast.day01.demo07;

public class MyInterfaceABimpl implements MyInterface{
    @Override
    public void mathod1() {
        System.out.println("A覆盖重写了1方法");
    }
    @OverrideA
    public void mathod2() {
        System.out.println("B覆盖重写了2方法");
    }

    @Override
    public void abs() {
        System.out.println("覆盖重写了A和B接口都有的【抽象方法】abs");
    }
    @Override
    public void method() {
        System.out.println("覆盖重写方法");
    }
     @Override
     public default void defaultmethod(){
        System.out.println("带着子接口【default】关键字,对默认方法进行覆盖重写");
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值