抽象类和接口

        总体上来讲,抽象类和接口主要使用的就是多态,接口之间可以多继承其间用逗号隔开,类可以实现多个接口,其间都用逗号隔开

目录

1.抽象类

       1.什么是抽象类

        2.抽象类的作用

        3.抽象类怎样创建

        4.抽象类里面可以包含什么

       5.抽象类的特殊性

        6.抽象方法

        7.final关键字

2.接口(也是一种类)

        1.什么是接口

        2.接口的作用:

        3.定义一个接口

        4.接口的实现

        5.接口的继承

        6.接口的使用

        7.注意

        8.综合代码

        9.default和static定义的方法


 

1.抽象类

       1.什么是抽象类

                abstract修饰的类就是抽象类

                理解的时候就可以理解成:把类进行抽象得到的就是抽象类,就当成对象抽象成类,类抽象成抽象类那样理解就可以

                类是对于对象共同属性和行为的抽象

                抽象类是类的抽象

                正如刚才所说,抽象类是类的抽象,所以不可以直接生成对象,也就是说,其实抽象类不可以实例化。

        2.抽象类的作用

                抽象类天生就是用来被继承的,天生就是爹

        3.抽象类怎样创建

                【访问权限修饰符】【修饰符】 abstract class 类名{类体}

                即在"class"前写一个abstract

                eg:public abstract class ChouXiang(){}  

        4.抽象类里面可以包含什么

                1.构造方法:

                        虽然抽象类不能实例化无法进行对象的创建,但是它有构造方法,是为子类创建对象用的,子类实例化对象的时候会使用super调用父类这个构造方法

                2.属性

                3.方法

                4.抽象方法

       5.抽象类的特殊性

                抽象类具有抽象方法

        6.抽象方法

                包含抽象方法的类必须是抽象类

                1.什么是抽象方法

                        被abstract修饰的方法就是抽象方法

                        特征:没有方法体和那个大括号

                2.抽象方法的作用(又或者说为什么要用抽象方法):

                        由于一些方法的实用性不高,比如如果人类和猫类都继承了动物的行走行为,此时动物类是抽象类,人类和猫类都是普通的类,由于行走这个行为对人而言是双脚走,对猫而言是四脚着地,所以此时不同的方法应用下来就不一样了,就需要使用抽象方法,先定义出来这个方法再根据不同的子类来重写各自的方法(记住使用@Override)

                3.形式:

                        【访问权限修饰符】 【修饰符】 abstract 返回值 方法名(形参列表);

                对于抽象方法而言,不需要写方法体,包括那个大括号也不用写,只需要定义出来就可以,这种格式就像是c语言先定义,然后再写方法体一样,只不过java是在子类当中重写方法体

                4.在写了抽象方法之后一定要进行所有抽象方法的重写(除非子类也是抽象类)

                5.重写抽象类的时候要把abstract去掉的同时加上方法体和大括号

                6.抽象类里面不一定有抽象方法,也就是说,可以但没必要

                7.普通的类里面的方法不一定有方法体,例如用native修饰的内容可以没有方法体,而是去调用底层C语言,也就是说普通类里的方法不一定都有方法体,

                    即普通类里的方法一定有方法体        ( X )。

                8.final修饰的方法不可能是抽象方法,final修饰的类不能被继承,也就是说final和abstract不能同时出现

一个账户包括账号密码和余额,还有一个打印余额的方法
工行和农行都使用了这个账户的内容
public abstract class Account {
    private String accountNum;
    private String password;
    private int money;
    public Account(){
    }
    public Account(String accountNum,String password){
        this.password = password;
        this.accountNum = accountNum;
    }
    public String getAccountNum(){
        return accountNum;
    }

    public String getPassword() {
        return password;
    }
    public int getMoney() {
        return money;
    }
    public void setAccountNum(String accountNum){
        this.accountNum = accountNum;
    }
    public void setPassword(String password){
        this.password = password;
    }
    public void setMoney(int money) {
        this.money = money;
    }
    public abstract void showMoney();
}


public class Credit extends Account{
    public Credit(){
    }
    public Credit(String accountNum,String password){
        super(accountNum,password);
    }
    @Override
    public void showMoney(){
        System.out.println("当前工行余额为:"+super.getMoney());
    }
}


public class CreditNongHang extends Account{
    public CreditNongHang(){
    }
    public CreditNongHang(String accountNum,String password){
        super(accountNum,password);
    }
    @Override
    public void showMoney(){
        System.out.println("当前农行余额为:"+super.getMoney());
    }
}


public class Test {
    public static void main(String[] args) {
        Account a = new Credit("123","123");
        Account b = new CreditNongHang("123","123");
        a.setMoney(500000);
        b.setMoney(400000);
        a.showMoney();
        b.showMoney();
    }
}

        7.final关键字

                1.是个修饰符

                2.修饰内容:

                        修饰类:该类无法被继承

                        修饰方法:该方法无法被重写

                        修饰成员变量:使成员变成常量无法被更改,此时一定要在类里面给这个常量进行赋值,否则会发生报错因为按常理的:不赋值的话JVM会给默认数据,无法再更改,但是成员属性就是程序员要规定的内容,不认为规定数据就失去了成员变量原有的意义,所以SUN公司不对final修饰的常量赋初值
                        修饰局部变量(形参列表和方法体内的变量都是局部变量):使得该变量无法被更改

2.接口(也是一种类)

        1.什么是接口

                现实当中某些类出现了本不属于自己的方法,例如猫跳圈,老虎钻火圈,像是这种额外的方法,就需要用接口来写下来,然后让这些普通类来实现

                接口是一个特殊的抽象类,他只包括抽象方法和常量,不可以包括普通的方法(jdk1.8之后加上某些关键字也可以包括普通方法)(接口的抽象方法加上个default修饰后可以写方法体,这个default不是前面包和权限的(default),这个default是一个切实存在的关键字)

                接口没有构造方法

        2.接口的作用:

                接口可以理解成行为的抽象,只关注行为,不关注完成这个行为的对象是否合理,就比如抽象方法是写字,一个杯子实现了这个接口,那么杯子就会重写抽象方法,但是杯子的对象难道能写字?所以说不合理,但是我依旧是让这个杯子类实现了这个接口,也就是说我这个接口根本不在乎对象的合理性,只在乎一个行为

        3.定义一个接口

                public interface 接口名 { 常量; 抽象方法; }

        4.接口的实现

                接口也是抽象类的一种,不能够直接创建对象,所以它需要有实现这个接口的类,接口不可以被类继承,只可以被接口继承

                使用implements实现接口,在一个类当中可以实现多个接口但是这些接口必须要用逗号间隔开

public class Anmail implements Fly,Run{
    @Override
    public void fly(){
        System.out.println("在飞");
    }
    public void run(){
        System.out.println("在跑");
    }
}

                如果一个类又有继承又有实现,那么就先继承后实现

                如果继承了一个实现了接口的父类,那么此时这个子类不需要再重写抽象方法(这个是考虑子类既有继承又有实现的情况,如果子类和父类实现了同一个接口,而且父类已经重写了这个接口的抽象方法,那么子类就没必要重写了,可以但没必要)

public class Cat extends Anmail implements Run{
    //之所以这里让猫飞是为了让理解一下接口的作用,即不考虑对象的合理性,本不属于该类的行为赋予给了这个类
    @Override
    public void fly(){
        System.out.println("猫在飞");
    }
    //此处不报错,说明由于在Anmail中重写了run抽象方法所以此处就不用重写了
}

                在接口的实现类当中必须重写所有的抽象方法(default修饰的抽象方法可以不重写)

        5.接口的继承

                接口只可以继承接口,接口不可以继承类也不可以被类继承,甚至不可以继承Object

(接口如果继承类的话那么就会有普通的方法了,就不想原先那样纯粹只有抽象方法和常量了)

                一个接口可以继承多个接口,虽然类是单继承的,但是接口是多继承的(这和没有构造方法有一定意义的关系)

public interface MoveWay extends Run,Fly{
    //这里是体现接口的多继承
}

        6.接口的使用

                接口虽然不能继承被继承但是可以被实现,在使用接口的时候也是使用多态,此时虽然接口不是父类,但是可以当作父类来使用。

                如果说两个接口的都被同一个子类实现了,那么这两个接口创建出来的“引用”在instanceof的比较下为true,因为instanceof是看某一个引用是否可以转化为另一个类的引用,由于接口1和接口2都被类1实现了,此时可以理解为接口1先转成类1再转成接口二

public class Test {
    public static void main(String[] args) {
        Fly a = new Cat();
        a.fly();//此处是FLy的引用调用Cat的方法
        //由于run方法是Cat当中有但是a当中没有的,所以此a需要向下转型转为Cat
        if(a instanceof Cat){
            ((Cat)a).run();//此处就可以调用特有的方法了
        }
        //由上述内容可见仍然是以多态的方式来使用接口
        Fly b = new Anmail();
        b.fly();//此处是Fly的引用调用Anmail的方法
        System.out.println(a instanceof Anmail);//由于a属于Cat,Cat是Anmail的子类,所以此处是true
        System.out.println(b instanceof Cat);//此处毫无影响。直接false
        Run c = new Cat();
        System.out.print("c");
        c.run();
        System.out.println(a instanceof Run);
    }
}

        7.注意

                接口里面的属性和方法都必须是public的,由于这种特性,所以在接口当中public abstract和public final可以不写,这两个东西在编译的时候会自动加上

public interface Fly {
    int flyMaxHeight = 500;
    void fly();
}

        8.综合代码

public interface Fly {
    public abstract void fly();
}


public interface Run {
    void run();
}


public interface MoveWay extends Run,Fly{
    //这里是体现接口的多继承
}


public class Anmail implements Fly,Run{
    @Override
    public void fly(){
        System.out.println("在飞");
    }
    public void run(){
        System.out.println("在跑");
    }
}


public class Cat extends Anmail implements Run{
    //之所以这里让猫飞是为了让理解一下接口的作用,即不考虑对象的合理性,本不属于该类的行为赋予给了这个类
    @Override
    public void fly(){
        System.out.println("猫在飞");
    }
    //此处不报错,说明由于在Anmail中重写了run抽象方法所以此处就不用重写了
}


public class Test {
    public static void main(String[] args) {
        Fly a = new Cat();
        a.fly();//此处是FLy的引用调用Cat的方法
        //由于run方法是Cat当中有但是a当中没有的,所以此a需要向下转型转为Cat
        if(a instanceof Cat){
            ((Cat)a).run();//此处就可以调用特有的方法了
        }
        //由上述内容可见仍然是以多态的方式来使用接口
        Fly b = new Anmail();
        b.fly();//此处是Fly的引用调用Anmail的方法
        System.out.println(a instanceof Anmail);//由于a属于Cat,Cat是Anmail的子类,所以此处是true
        System.out.println(b instanceof Cat);//此处毫无影响。直接false
        Run c = new Cat();
        System.out.print("c");
        c.run();
        System.out.println(a instanceof Run);

    }
}

        9.default和static定义的方法

       static和default放的位置和abstract的位置一样,但是这里的意思是static不可重写而且是静态的方法,default还可以重写(可以但没必要),写了这两种当中的任意一种就不用写abstract了

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