码迷,mamicode.com
首页 > 编程语言 > 详细

java基础(4)继承

时间:2019-01-20 00:57:31      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:his   main   一个   ace   修改   abs   sys   extends   自己   

1 继承

1.1  继承概述

继承要解决的问题:共性抽取

1.2 继承的格式

class 父类 {
...
}
class 子类 extends 父类 {
...
}

 

1.3 继承中成员变量的特点(变量重名)

1.3.1 子类父类成员变量重名

  • 规则1:直接通过子类访问成员变量:

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

  • 规则2:间接通过成员方法访问成员变量:

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

//定义父类
public class Fu {
    int num = 10;

    public int method(){
        return num;
    }
}
//定义子类
public class Zi extends Fu{
    int num = 20;//与父类成员变量重名
}
//
public class demo01 {
    public static void main(String[] args) {
        Fu fu = new Fu();
        Zi zi = new Zi();

        System.out.println(fu.num);//输出10,Fu fu = new Fu()等号左边是Fu,所以去Fu类中找成员变量num
        System.out.println(zi.num);//输出20,Zi zi = new Zi() 等号左边是Zi,所以在Zi类中找成员变量num
 System.out.println(fu.method()); //10,方法属于父类
System.out.println(zi.method()); //10,方法属于父类
}
}

 

1.3.2 三种变量重名

子类方法的局部变量:直接写成员变量

子类的成员变量:this.

父类的成员变量:super.

class Fu {
// Fu中的成员变量。
int num = 10;
}

class Zi extends Fu {
// Zi中的成员变量
int num = 20;
public void show() {
int num = 30; System.out.println(
"local num=" + num); //访问父类中的num System.out.println("Fu num=" + super.num); //访问子类中的num System.out.println("Zi num=" + this.num); } } class ExtendsDemo03 { public static void main(String[] args) { // 创建子类对象 Zi z = new Zi(); // 调用子类中的show方法 z.show(); } }
//
10
20
30

 

1.4 继承中成员方法的访问特点

成员方法不重名:

对象调用方法时,会先在子类中查找有没有对
应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。

 

成员方法重名——重写(Override)

class Fu {
public void show() {
System.out.println("Fu show");
}
}
class Zi extends Fu {
//子类重写了父类的show方法
public void show() {
System.out.println("Zi show");
}
}
public class ExtendsDemo05{
public static void main(String[] args) {
Zi z = new Zi();
// 子类中有show方法,只执行重写后的show方法
z.show(); // Zi show
}
}

总结:在调用子类成员变量和成员方法时,如果子类中有的,就先用自己的。没有再找父类。方法是谁的,就优先用谁的。

 

重写和重载的区别:

重写override:方法的名称一样,参数列表页一样;

@override 注解,可以检测重写是否正确

重载overload:方法的名称一样,参数列表不一样。

 

重写权限:子类方法的权限必须大于等于父类方法的访问权限

public>protected>(default)>private

其中default是留空

 

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

  • 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构
    造方法中默认有一个super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。

public class Fu {
    public Fu(){
        System.out.println("Father Constrictor");
    }
}

public class Zi extends Fu {
    public Zi(){
        System.out.println("Son Constrictor");
    }
}

public class Constructor {
    public static void main(String[] args) {
        Zi zi = new Zi();//默认会调用super(),无参构造方法
    }
}

//
Father Constrictor
Son Constrictor
  • 子类构造可以通过super调用父类重载构造,且只能用一次super
  • 子类必须调用父类构造方法,不写则默认赠送super()无参构造,写了则用指定的super()方法

1.6 super和this的几种用法

技术分享图片

 

技术分享图片

 

1.6 this当前对象的一点总结

//创建父类
public
class User { String name; private double leftMoney; public User() { } public User(String name, double leftMoney) { this.name = name; this.leftMoney = leftMoney; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getLeftMoney() { return leftMoney; } public void setLeftMoney(double leftMoney) { this.leftMoney = leftMoney;////子类对象去调用父类方法时,并没有创建父类对象。this指针指的是调用该方法的对象(子类对象),所以这里的this指的是子类对象}
  public void show(){ 
    System.out.println(
"用户名:"+name+"余额:"+leftMoney);
}
}


//创建子类
public class Manager extends User { public Manager(){ } public Manager(String name, double money){ super(name,money); } public void setLeft(double redTotal){ double leftMoney = super.getLeftMoney(); super.setLeftMoney(leftMoney-redTotal); } }
//创建main方法
public class redMain { public static void main(String[] args) { Manager manager = new Manager("Manager",200); manager.show();//输出:用户名:Manager余额:200.0 manager.setLeft(10);//子类对象去调用父类方法时,并没有创建父类对象。this指针指的是调用该方法的对象(子类对象) manager.show();//输出:用户名:Manager余额:190.0
} }

 

2 接口

2.1 概述

  • 接口是多个类的公共规范;
  • 接口是一种引用数据类型,最重要的是其中的抽象方法;接口也会被编译成.class文件,但一定要明确它并不是类,而是另外一种引用数据类型。
  • 引用数据类型:数组,类,接口。
  • 接口是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法(JDK 9)。
  • 接口的使用:它不能创建对象,但是可以被实现( implements ,类似于被继承)。一个实现接口的类(可以看做
    是接口的子类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法了,否则它必须是一个抽象
    类。

2.2 接口定义

//定义格式
public
interface 接口名称 { // 抽象方法 // 默认方法 // 静态方法 // 私有方法 }

2.2.1 接口中的抽象方法定义和使用

public interface MyInterfaceAbstract {
    public abstract void methodAbstract();//不能有大括号
//    private abstract void methodAbstrac2();//错误,只能用public
    abstract void methodAbstrac3();//可以省略public
    void methodAbstrac4();//可以同时省略public abstract
}

 

接口的使用:

  • 接口不能直接new对象使用。必须有一个实现类类实现该接口
  • 类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类

    似继承,格式相仿,只是关键字不同,实现使用 implements 关键字。

  • 非抽象子类实现接口:

    1. 必须重写接口中所有抽象方法。
    2. 继承了接口的默认方法,即可以直接调用,也可以重写。

public class MyInterfaceAbstractImpl implements MyInterfaceAbstract{
    @Override
    public void methodAbstract() {
        
    }

    @Override
    public void methodAbstrac3() {

    }

    @Override
    public void methodAbstrac4() {

    }
}

2.2.2 接口中的默认方法定义和使用

默认方法的作用:

实现类会继承接口中的抽象方法。当接口升级(添加新方法)的时候,将该新方法定义为default,则已存在的实现类中不用添加代码去实现该方法(如果新方法在接口中定义为abstract,则实现类必须要实现该方法,会增加很多工作量)。

//定义接口
public interface MyInterfaceDefault {
    public abstract void methodAbs();
    public default void methodDeft(){
        System.out.println("接口的default方法");
    }
}

//实现类
public class MyInterfaceDefaultImplA implements MyInterfaceDefault {
    @Override
    public void methodAbs() {
        System.out.println("实现类的抽象方法");
    }
}

//主函数
public class demoMyDefault {
    public static void main(String[] args) {
        MyInterfaceDefaultImplA implA = new MyInterfaceDefaultImplA();
        implA.methodAbs();
        implA.methodDeft();//默认继承了接口的default方法,实现类中可以不用写,直接调用;也可以重写
    }
}

//输出
实现类的抽象方法
接口的default方法

 

2.2.3 接口中的静态方法定义和使用

/*
从Java 8开始,接口当中允许定义静态方法。
格式:
public static 返回值类型 方法名称(参数列表) {
    方法体
}
提示:就是将abstract或者default换成static即可,带上方法体。
 */
public interface MyInterfaceStatic {

    public static void methodStatic() {
        System.out.println("这是接口的静态方法!");
    }

}

/* 注意事项:不能通过接口实现类的对象来调用接口当中的静态方法。 正确用法:通过接口名称,直接调用其中的静态方法。 格式: 接口名称.静态方法名(参数); */ public class Demo03Interface { public static void main(String[] args) { // 创建了实现类对象 MyInterfaceStaticImpl impl = new MyInterfaceStaticImpl(); // 错误写法!不能用实现类的对象来调用接口中的静态方法 // impl.methodStatic(); // 直接通过接口名称调用静态方法 MyInterfaceStatic.methodStatic(); } }

 

2.2.4 接口中的私有方法定义和使用

/*
问题描述:
我们需要抽取一个共有方法,用来解决两个默认方法之间重复代码的问题。
但是这个共有方法不应该让实现类使用,应该是私有化的。

解决方案:
从Java 9开始,接口当中允许定义私有方法。
1. 普通私有方法,解决多个默认方法之间重复代码问题
格式:
private 返回值类型 方法名称(参数列表) {
    方法体
}

2. 静态私有方法,解决多个静态方法之间重复代码问题
格式:
private static 返回值类型 方法名称(参数列表) {
    方法体
}
 */

//对默认方法的重复代码私有化
public interface MyInterfacePrivateA { public default void methodDefault1() { System.out.println("默认方法1"); methodCommon(); } public default void methodDefault2() { System.out.println("默认方法2"); methodCommon(); } private void methodCommon() { System.out.println("AAA"); System.out.println("BBB"); System.out.println("CCC"); } }
//在接口中,对静态方法的重复代码的私有化
public interface MyInterfacePrivateB {

    public static void methodStatic1() {
        System.out.println("静态方法1");
        methodStaticCommon();
    }

    public static void methodStatic2() {
        System.out.println("静态方法2");
        methodStaticCommon();
    }

    private static void methodStaticCommon() {
        System.out.println("AAA");
        System.out.println("BBB");
        System.out.println("CCC");
    }

}

 

2.3 接口中的常量定义

/*
接口当中也可以定义“成员变量”,但是必须使用public static final三个关键字进行修饰。
从效果上看,这其实就是接口的【常量】。
格式:
public static final 数据类型 常量名称 = 数据值;

注意事项:
1. 接口当中的常量,可以省略public static final,注意:不写也默认是public static final。
2. 接口当中的常量,必须进行赋值。
3. 接口中常量的名称,使用完全大写的字母,用下划线进行分隔。(推荐命名规则)
 */
public interface MyInterfaceConst {

    // 这其实就是一个常量,一旦赋值,不可以修改
    public static final int NUM_OF_MY_CLASS = 12;

}

 

2.4 接口的多实现和多继承

在继承体系中,一个类只能继承一个父类。而对于接口而言,一个类是可以实现多个接口的,这叫做接
口的多实现。并且,一个类能继承一个父类,同时实现多个接口。

格式:
class 类名 [extends 父类名] implements 接口名1,接口名2,接口名3... {
// 重写接口中抽象方法【必须】
// 重写接口中默认方法【不重名时可选】
}

[ ]: 表示可选操作。

2.4.1 多实现会出现以下的问题:

/*
使用接口的时候,需要注意:

1. 接口是没有静态代码块或者构造方法的。
2. 一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
格式:
public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB {
    // 覆盖重写所有抽象方法
}
3. 如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。
4. 如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。
5. 如果实现类所实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写(两个默认方法都不用,自己重新覆盖重写)。
6. 一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法。
 */
public class Demo01Interface {

    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.method();
    }

}

 

//第1点
public interface MyInterfaceA {

    // 错误写法!接口不能有静态代码块
//    static {
//
//    }

    // 错误写法!接口不能有构造方法
//    public MyInterfaceA() {
//
//    }

    public abstract void methodA();

    public abstract void methodAbs();

    public default void methodDefault() {
        System.out.println("默认方法AAA");
    }

}

 

public interface MyInterfaceB {

    // 错误写法!接口不能有静态代码块
//    static {
//
//    }

    // 错误写法!接口不能有构造方法
//    public MyInterfaceA() {
//
//    }

    public abstract void methodB();

    public abstract void methodAbs();

    public default void methodDefault() {
        System.out.println("默认方法BBB");
    }

}

 

//第2点和第3点
public class MyInterfaceImpl /*extends Object*/ implements MyInterfaceA, MyInterfaceB {

    @Override
    public void methodA() {
        System.out.println("覆盖重写了A方法");
    }


    @Override
    public void methodB() {
        System.out.println("覆盖重写了B方法");
    }

    @Override
    public void methodAbs() {
        System.out.println("覆盖重写了AB接口都有的抽象方法");
    }

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

 

//第6点
//优先级,继承优先于接口
public class Fu {

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


public class Zi extends Fu implements MyInterface {
}

 

2.4.2 多继承注意事项

/*
1. 类与类之间是单继承的。直接父类只有一个。
2. 类与接口之间是多实现的。一个类可以实现多个接口。
3. 接口与接口之间是多继承的。

注意事项:
1. 多个父接口当中的抽象方法如果重复,没关系。
2. 多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写,【而且带着default关键字】。
 */
public class Demo01Relations {
}
public interface MyInterfaceA {
    public abstract void mehtodA();
    public abstract void methodCom();
    public default void methodDef(){
        System.out.println("AAA");
    }
}

public interface MyInterfaceB {
    public abstract void mehtodB();
    public abstract void methodCom();
    public default void methodDef(){
        System.out.println("BBB");
    }
}

public interface MyInterface extends MyInterfaceA,MyInterfaceB{
    public abstract void mehtod();

    @Override
    default void methodDef() {//必须重写default方法

    }
}

 

java基础(4)继承

标签:his   main   一个   ace   修改   abs   sys   extends   自己   

原文地址:https://www.cnblogs.com/JohnTeslaaa/p/10290737.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!