栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java学习之旅(四六):抽象类与接口

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java学习之旅(四六):抽象类与接口

通常可以说四边形具有四条边,或者也可以说平行四边形是具有对边平行且相等的特征的特殊四边形,等腰三角形是具有两条边相等的特性的特殊三角形,这些文字的描述都是和合乎情理的。但对于图形图像来说,却不能使用具体的语言进行描述,它有几条边,究竟是什么图形,没有人能够说清楚,这种类在 Java 中被定义为抽象类。

抽象类

在解决实际问题时,一般将父类定义为抽象类,需要使用父类进行继承与多态处理。在继承树中,越是在上方的类越抽象,如平行四边形类继承四边形类,四边形类继承图形类,又比如鸽子类继承鸟类,鸟类继承动物类等。但是在多态体制中,并不需要将父类初始化对象,我们需要的只是子类的对象,所以在 Java 中设置抽象类不可以实例化对象,因为图形类不能抽象出任何一种具体图形,但它的子类却可以。抽象类的定义语法如下:

public abstract class Test {
    // 定义抽象方法
    abstract void print();
}

其中, abstract 为定义抽象类的关键字。使用 abstract 关键字定义的类称为抽象类,而是用这个关键字定义的方法称为抽象方法。抽象方法没有方法体,这个方法本身没有任何意义,除非它被重写,而承载这个抽象方法的抽象类必须被继承,实际上抽象类除了被继承也没有其他意义。

反过来说就是,如果声明一个抽象的方法,就必须将承载这个抽象方法的类定义为抽象类,不可能在非抽象类中获取抽象方法。只要类中有一个抽象方法,这个类就要被标记为抽象类。

抽象类被继承后需要实现其中所有的抽象方法,也就是保证相同的方法名称、参数列表和相同的返回值类型创建出非抽象方法,当然也可以是抽象方法。

如上图所示,创建一个 Graph 的抽象类,其中有两个抽象方法 draw() 和 say(),接着又创建了 Quadrilateral 类和 Triangle 类,这两个类都继承了 Graph 类,所以都需要去重写 Graph 类中的两个抽象方法,除此之外,Quadrilateral 类中又声明了一个 doAnything() 的抽象方法,所以 Quadrilateral 类也是一个抽象类,该类中总共有三个方法,之后又创建了 Square 类和 Parallelogram 类去继承 Quadrilateral 类,自然而然需要重写 Quadrilateral 类中的抽象方法 doAnything()。

继承抽象类的所有子类需要将抽象类中的所有抽象方法进行覆盖重写。这样在多态机制中,就可以将父类修改为抽象类。如,将 draw() 方法设置为抽象方法,然后每个子类都去重写这个方法,但这样就会出现冗余代码,同时这样的父类局限性很大,也许某个子类不需要 draw() 方法,但是因为继承了抽象类,所以也不得不去重写这个 draw() 方法。如果将 draw() 方法放置在另外一个类中,让需要 draw() 方法的子类去继承该类,不需要 draw() 方法的子类只需要正常去继承抽象类即可。但是这样又有一个问题,所有的子类都需要 Graph 类,因为这些类都是从 Graph 类中导出的,同时某些子类还需要 draw() 方法,而 Java 中规定类不能同时继承多个父类。于是,接口的概念便产生了。

接口

接口是抽象类的延伸,可以将它看作是纯粹的抽象类,接口中的所有方法都没有方法体。比如我们上面说的这个问题,我们可以考虑将 draw() 方法封装到一个接口中,使需要 draw() 方法的类去实现这个接口,同时也继承图形类,这就是接口存在的必要性。

接口使用 interface 关键字进行定义,其语法为:

public interface drawTest() {

    void draw();

}

其中,interface 是用来声明接口类的关键字,public 是接口权限的修饰符,drawTest 是接口名称。一个类要实现该接口的话需要使用 implements 关键字。

在接口中,方法必须被定义为 public 或 abstract 形式,其他修饰权限不被 Java 编译器认可。或者说,即使不将该方法声明为 public 形式,它也是 public 形式。在接口中定义的任何字段都自动是 static 和 final 的。

示例:在项目中创建一个四边形类,并且在该类中创建两个继承该类的内部类,平行四边形类和正方形类;然后再另一个文件中创建 Draw 接口类,声明 draw() 方法,并使平行四边形和正方形两个内部类去实现该接口;然后在主方法中分别调用这两个内部类的 draw() 方法。

// 声明接口类
public interface Draw {

    public void draw();

}



public class Quadrilateral {

    public void doAnything() {

    }

    class Parallelogram extends Quadrilateral implements Draw {

        @Override
        public void draw() {
            System.out.println("平行四边形类继承了四边形类,并实现了Draw接口类中的draw()方法");
        }

        @Override
        public void doAnything() {
            // 继承了四边形类,所以需要覆盖父类的方法
        }

    }

    class Square extends Quadrilateral implements Draw {

        @Override
        public void doAnything() {
            // 继承了四边形类,需要覆盖父类的方法
        }

        @Override
        public void draw() {
            System.out.println("正方形类继承了四边形类,并实现了Draw接口类中的draw()方法");
        }

    }

    public static void main(String[] args) {
        Draw[] quadrilaterals = {
                new abstractClass.Parallelogram(),
                new abstractClass.Square()
        };
        for (int i = 0; i < quadrilaterals.length; i++) {
            quadrilaterals[i].draw();
        }
    }

}

运行 main() 方法,得到如下结果:

正方形类和平行四边形类分别实现了 Draw 接口并继承了四边形类,所以需要覆盖接口中的 draw() 方法。在调用 draw() 方法时,首先将平行四边形类对象与正方形类对象向上转型为 Draw 接口形式。在 Java 中,无论是将一个类向上转型为父类对象还是向上转型为抽象父类对象,或者向上转型为该类的实现接口,都是没有问题的。

Java 中不允许出现多继承,但使用接口就可以实现多继承。一个类可以同时实现多个接口,因此也可以将所有需要继承的接口放在 implements 关键字之后并使用逗号隔开。但这可能会在另一个类中产生庞大的代码量,因为继承一个接口时需要实现接口中所有的方法。

多重继承的语法为:

class 类名 implements 接口1,接口2,...

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/781812.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号