【剧前爆米花--爪哇岛寻宝】抽象类和接口——理论及逻辑理解

作者:困了电视剧

专栏:《JavaSE语法与底层详解》

文章分布:这是一篇关于抽象类和接口的文章,在本篇文章中我会介绍其相关的定义和语法,并且揭示接口和抽象类的运行逻辑,提高对面对象编程的理解。

【剧前爆米花--爪哇岛寻宝】抽象类和接口——理论及逻辑理解_第1张图片

目录

抽象类

抽象类概念及其语法

抽象类特性

抽象类作用

接口 

接口的概念和语法

接口的特性

接口和上转型在项目中被使用的逻辑(核心)

类,抽象类,接口的比较


抽象类

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的, 如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
举个栗子:我现在有个动物类,动物都有一个行为那就是发出叫声,我可以定义一个Cat类继承这个动物类,然后Cat类在通过多态实现不同的行为——喵喵叫,此时如果我将动物类定义为一个普通类,那动物类就有一个叫声的行为,但是由于每个动物的叫声都不一样,那么此时这个动物类的叫声就发生了逻辑上的错误,即我不知道它是什么动物,无法判断它的叫声。
而如果我们把这个动物类设计成一个抽象类,那么我们就可以将这个叫声的方法设置成抽象方法,从而实现逻辑上的自洽,并且利用编译器的语法纠错提高程序的安全性。

抽象类概念及其语法

Java 中,一个类如果被 abstract 修饰称为抽象类,抽象类中被 abstract 修饰的方法称为抽象方法,抽象方法不用 给出具体的实现体。
注意: 抽象类也是类,内部可以包含普通方法和属性,甚至构造方法。
abstract class Animal{
    int age;
    String name;
    String sex;
    //构造方法
    public Animal(int age, String name, String sex) {
        this.age = age;
        this.name = name;
        this.sex = sex;
    }
    public Animal(){}
    //抽象方法
    public abstract void eat();
    public abstract void speak();
    //普通方法
    public void sleep(){}
}

抽象类特性

1. 抽象类不能直接实例化对象
2. 抽象方法不能是 private
3. 抽象方法不能被 final static 修饰,因为抽象方法要被子类重写
4. 抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必      须要使用 abstract 修饰
5. 抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类
6. 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量
解释:1.这一点是设计抽象类提高代码安全性的核心特性,就像我前文说的那样,有的时候一个类并不能表现一个特定的行为,但是当我们将它定义成普通类时,它就可以进行实例化,从而进行相应的行为,这在逻辑上并不自洽。
当我们用抽象类对其进行定义的时候,由于其不能进行实例化,所以就不会表现出相应的行为,减少了出错的可能,提高了代码的安全性。
2.重写是子类对父类的允许访问的方法的实现过程进行重新编写,用private修饰不论是不是抽象方法都不能进行重写。
abstract class Animal{
    int age;
    String name;
    String sex;
    //构造方法
    public Animal(int age, String name, String sex) {
        this.age = age;
        this.name = name;
        this.sex = sex;
    }
    public Animal(){}
    //抽象方法
    public abstract void eat();
    public abstract void speak();
    //普通方法
    private void sleep(){}
}

class Cat extends Animal{
    @Override
    public void eat() {

    }

    @Override
    public void speak() {

    }
    @Override
    public void sleep(){
        System.out.println("aaaaaa");
    }
}

这段代码会报错

【剧前爆米花--爪哇岛寻宝】抽象类和接口——理论及逻辑理解_第2张图片

4.由于抽象类并不能实例化对象,所以如果抽象类想要被使用的话就必须被继承,被继承到子类时也是抽象方法,所以如果子类不对其进行重写,则子类包含抽象方法,只能用抽象类来进行定义。

抽象类作用

使用抽象类的场景就如上面的代码 , 实际工作不应该由父类完成 , 而应由子类完成 . 那么此时如果不小心误用成父类了, 使用普通类编译器是不会报错的 . 但是父类是抽象类就会在实例化的时候提示错误 , 让我们尽早发现问题。
很多语法存在的意义都是为了 " 预防出错 ", 例如我们曾经用过的 final 也是类似 . 创建的变量用户不去修改 , 不就相当于常量嘛? 但是加上 fifinal 能够在不小心误修改的时候 , 让编译器及时提醒我们。

接口 

接口的概念和语法

接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用 。在Java 中,接口可以看成是:多个类的公共规范,是一种引用数据类型。
接口的定义格式与定义类的格式基本相同,将 class 关键字换成 interface 关键字,就定义了一个接口。
Java 中,类和类之间是单继承的,一个类只能有一个父类,即 J ava中不支持多继承 ,但是 一个类可以实现多个接口
注意:一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类
Java 中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。即:用接口可以达到 多继承的目的。
接口可以继承一个接口 , 达到复用的效果 . 使用 extends 关键字
public interface Code {
    public abstract void test1();
    public abstract void test2();
}

interface Code_test1 extends Code{
    public abstract void test3();
}

interface Code_test2 extends Code,Code_test1{
    public abstract void test4();
}
class Test1 implements Code,Code_test1,Code_test2{
    @Override
    public void test1() {
        
    }

    @Override
    public void test2() {

    }

    @Override
    public void test3() {

    }

    @Override
    public void test4() {

    }
}

接口的特性

1. 接口类型是一种引用类型,但是不能直接 new 接口的对象
2.  接口中每一个方法都是 public 的抽象方法 , 即接口中的方法会被隐式的指定为 public   abstract (只能是public abstract,其他修饰符都会报错 )
3. 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现
4. 重写接口中方法时,不能使用默认的访问权限
5. 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static fifinal 变量
6. 接口中不能有静态代码块和构造方法
7. 接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是 .class
8. 如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类
9. jdk8 中:接口中还可以包含 default 方法。

解释:

1.原因与抽象类类似,都是旨在提高代码的安全性,并且保证逻辑上的自洽。

2. 第二点和第五点中方法和变量前面的修饰符可加可不加,也可不加完,但在实际的项目中为了保证代码的简洁和统一,一般什么都不加。

public interface Code {
    int a=0;
    final int b=0;
    public final int c=0;
    public abstract void test1();
    public void test2();
}

interface Code_test1 extends Code{
    abstract void test3();
}

interface Code_test2 extends Code,Code_test1{
    void test4();
}
class Test1 implements Code,Code_test1,Code_test2{
    @Override
    public void test1() {

    }

    @Override
    public void test2() {

    }

    @Override
    public void test3() {

    }

    @Override
    public void test4() {

    }
}

 3.第四点中不能使用默认的类型是因为重写要求重写后的方法的访问权限不能低于重写前的方法,而在接口中默认的访问权限是public。

4.第七点编译后如图:

【剧前爆米花--爪哇岛寻宝】抽象类和接口——理论及逻辑理解_第3张图片

 可以看到后缀名也是.class。

接口和上转型在项目中被使用的逻辑(核心)

 接口的命名一般采用形容词性的单词。

我们来看一段代码:

public class Javabit_Code {
    public static void main(String[] args) {
        Animal cat=new Cat();
        Animal bird=new Bird();
        Action ac=new Action();
        ac.eat(cat);
        ac.eat(bird);
        ac.speak(cat);
        ac.speak(bird);
        ac.fly(new Bird());
    }
}

class Action{
    public void eat(Animal animal){
        animal.eat();
    }
    public void speak(Animal animal){
        animal.speak();
    }
    public void fly(Iflying animal){
        animal.fly();
    }
}

interface Iflying{
    void fly();
}

abstract class Animal{
    int age;
    String name;
    String sex;
    //构造方法
    public Animal(int age, String name, String sex) {
        this.age = age;
        this.name = name;
        this.sex = sex;
    }
    public Animal(){}
    //抽象方法
    public abstract void eat();
    public abstract void speak();
    //普通方法
    public void sleep(){}
}

class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("吃猫粮");
    }

    @Override
    public void speak() {
        System.out.println("喵喵叫");
    }
}

class Bird extends Animal implements Iflying{
    @Override
    public void eat() {
        System.out.println("吃鸟粮");

    }

    @Override
    public void speak() {
        System.out.println("叽叽喳喳");

    }

    @Override
    public void fly(){
        System.out.println("鸟在飞");
    }
}

在Action这个类中,我需要完成一些行为 ,但是此时由于我又不知道具体哪一个动物会被当做参数传进来,所以这里展现了多态的思想。

对于上转型来说,它提供了一种兼容,在Action类中的eat方法中,我需要传一个Animal的参数,这时我就可以运用上转型来完成这一点。

对于接口来说,它也提供了一种兼容,但和上转型又有点区别,上转型是“猫是动物”的关系即“is-a”的关系,而接口更像是“have-a”的关系,在本例中,他是只要实现了Iflying接口的类,其所实例化的对象就能当成参数,换个角度想,实现了Iflying接口就说明这个类实例化的对象会飞,而Action中的fly方法则是,只要是会飞的都可以实现这个方法。所以接口一般也用形容词进行命名。

这就是其中的逻辑关系。

类,抽象类,接口的比较

类就相当于一张盖楼用的图纸,我用这张图纸可以实例化一个楼。

抽象类就相当于没画完的图纸,这张图纸在某些地方,比如这栋楼的厕所建造时需要的信息没有画,只画了这个厕所要建在大致哪个位置,所以由于信息不全不能实例化一个楼。

接口,就相当于一套楼房大致框架的信息,你需要先把这些信息抄到一张图纸上,然后再在这张图纸上按照实际的需求进行补全,这样才能实例化一个大楼。

以上就是本篇文章的全部内容,如果对你有帮助还请三连,如有疏漏欢迎指正。

你可能感兴趣的:(JavaSE语法与底层详解,java,servlet,开发语言)