Java-接口与抽象类

Java-接口与抽象类

抽象类

如果编写一个类时,我们只想为该类定义一些方法,但是具体的实现交给继承它的子类来实现的话,我们可以考虑使用抽象类

抽象方法与抽象类

抽象方法与抽象类都必须使用abstract来修饰

  • 有抽象方法的类只能被定义为抽象类

  • 抽象类里面可以没有抽象方法

规则:

  • 抽象方法与抽象类都必须使用abstract来修饰,抽象方法不能有方法体

  • 抽象类不能实例化

  • 抽象类可以包含成员变量,方法(普通或者抽象方法都可以),构造函数,初始化块,内部类5种成分

  • 含有抽象方法的类只能被定义为抽象类

public abstract class Shape {

    {
        System.out.println("执行Shape的初始化块...");
    }
    private String color;
    // 定义一个计算周长的抽象方法
    public abstract double calPerimeter();
    // 定义一个返回形状的抽象方法
    public abstract String getType();
    // 定义Shape的构造器,该构造器并不是用于创建Shape对象,
    // 而是用于被子类调用
    public Shape(){}
    public Shape(String color)
    {
        System.out.println("执行Shape的构造器...");
        this.color = color;
    }
    // 省略color的setter和getter方法
    public void setColor(String color)
    {
        this.color = color;
    }
    public String getColor()
    {
        return this.color;
    }
}

public class Triangle extends Shape{

    // 定义三角形的三边
    private double a;
    private double b;
    private double c;
    public Triangle(String color , double a
            , double b , double c)
    {
        super(color);
        this.setSides(a , b , c);
    }
    public void setSides(double a , double b , double c)
    {
        if (a >= b + c || b >= a + c || c >= a + b)
        {
            System.out.println("三角形两边之和必须大于第三边");
            return;
        }
        this.a = a;
        this.b = b;
        this.c = c;
    }
    // 重写Shape类的的计算周长的抽象方法
    public double calPerimeter()
    {
        return a + b + c;
    }
    // 重写Shape类的的返回形状的抽象方法
    public String getType()
    {
        return "三角形";
    }


}

public class Circle extends Shape{

    private double radius;
    public Circle(String color , double radius)
    {
        super(color);
        this.radius = radius;
    }
    public void setRadius(double radius)
    {
        this.radius = radius;
    }
    // 重写Shape类的的计算周长的抽象方法
    public double calPerimeter()
    {
        return 2 * Math.PI * radius;
    }
    // 重写Shape类的的返回形状的抽象方法
    public String getType()
    {
        return getColor() + "圆形";
    }
    public static void main(String[] args)
    {
        Shape s1 = new Triangle("黑色" , 3 , 4, 5);
        Shape s2 = new Circle("黄色" , 3);
        System.out.println(s1.getType());
        System.out.println(s1.calPerimeter());
        System.out.println(s2.getType());
        System.out.println(s2.calPerimeter());
    }
}

注意:

  • static和abstract不能同时修饰某个方法

  • priva和abstract不能同时修饰方法

接口

抽象类是从多个类中抽象出来的模板,如果将这种抽象进行的更加彻底,那么就可以引出接口了

接口概念

接口是从多个相似类中抽象出来的规范,接口不提供任何实现,接口体现的是规范和实现分离的设计哲学

接口定义的基本语法:

[修饰符] interface 接口名 extends 父接口1,父接口2...
{
        0-n个常量定义...
        0-n个抽象方法定义...
        0-n个内部类、接口、枚举定义...
        0-n个私有方法、默认方法、类方法定义...
}

  • 修饰符可以是public或者省略,省略的话默认采用包权限访问控制符

  • 一个接口可以有多个直接父接口,但接口只能继承接口,不能继承类

接口中不能包含构造函数以及初始化块定义,可以包含成员变量(只能是静态常量),方法(只能是抽象实例方法、类方法、默认方法、私有方法),内部类(内部接口、枚举)定义

接口里面的常量、方法、内部类、内部枚举都是public访问权限,定义时可以省略访问控制修饰符,如果指定的话只能用public

接口里定义的静态常量系统会自动为这些变量增加static和final修饰符

接口里定义的成员变量只能在定义时指定默认值

接口里面如果不是定义默认方法、类方法、私有方法,系统自动为普通方法添加abstract修饰符,接口里面普通方法不能有方法实现;但是类方法、默认方法、私有方法都必须有方法实现

定义一个接口:

public interface Output {


    // 接口里定义的成员变量只能是常量
    int MAX_CACHE_LINE = 50;
    // 接口里定义的普通方法只能是public的抽象方法
    void out();
    void getData(String msg);
    // 在接口中定义默认方法,需要使用default修饰
    default void print(String... msgs)
    {
        for (String msg : msgs)
        {
            System.out.println(msg);
        }
    }
    // 在接口中定义默认方法,需要使用default修饰
    default void test()
    {
        System.out.println("默认的test()方法");
    }
    // 在接口中定义类方法,需要使用static修饰
    static String staticTest()
    {
        return "接口里的类方法";
    }


//    // 定义私有方法(要java9及其以上才可以)
//    private void foo()
//    {
//        System.out.println("foo私有方法");
//    }
//    // 定义私有静态方法
//    private static void bar()
//    {
//        System.out.println("bar私有静态方法");
//    }
}

接口的继承

接口的继承和类继承不一样,接口完全支持多继承,即一个接口可以有多个之间父接口,和类继承相似,子接口扩展某个父接口将会获得父接口里面定义的所有抽象方法,常量

一个接口继承多个父接口时,多个父接口排在extends关键字后面

interface InterfaceA
{
    int PROP_A = 5;
    void testA();
}
interface InterfaceB
{
    int PROP_B = 6;
    void testB();
}
interface InterfaceC extends InterfaceA, InterfaceB
{
    int PROP_C = 7;
    void testC();
}
public class InterfaceExtendsTest
{
    public static void main(String[] args)
    {
        System.out.println(InterfaceC.PROP_A);
        System.out.println(InterfaceC.PROP_B);
        System.out.println(InterfaceC.PROP_C);
    }
}


使用接口

接口不能用于创建实例,但是接口可以用于声明引用类型变量,此时这个引用类型变量必须引用到其实现类的对象

类实现接口语法:

[修饰符] class 类名 extends 父类 implement 接口1,接口2...

implement部分必须放置在extends后面

一个类实现了接口后,必须完全实现这些接口里面所定义的全部抽象方法,否则该类必须定义为抽象类


// 定义一个Product接口
interface Product
{
    int getProduceTime();
}
// 让Printer类实现Output和Product接口
public class Printer implements Output , Product
{
    private String[] printData
            = new String[MAX_CACHE_LINE];
    // 用以记录当前需打印的作业数
    private int dataNum = 0;
    public void out()
    {
        // 只要还有作业,继续打印
        while(dataNum > 0)
        {
            System.out.println("打印机打印:" + printData[0]);
            // 把作业队列整体前移一位,并将剩下的作业数减1
            System.arraycopy(printData , 1
                    , printData, 0, --dataNum);
        }
    }
    public void getData(String msg)
    {
        if (dataNum >= MAX_CACHE_LINE)
        {
            System.out.println("输出队列已满,添加失败");
        }
        else
        {
            // 把打印数据添加到队列里,已保存数据的数量加1。
            printData[dataNum++] = msg;
        }
    }
    public int getProduceTime()
    {
        return 45;
    }
    public static void main(String[] args)
    {
        // 创建一个Printer对象,当成Output使用
        Output o = new Printer();
        o.getData("hello");
        o.getData("world");
        o.out();
        o.getData("test");
        o.getData("case");
        o.out();
        // 调用Output接口中定义的默认方法
        o.print("孙悟空" , "猪八戒" , "白骨精");
        o.test();
        // 创建一个Printer对象,当成Product使用
        Product p = new Printer();
        System.out.println(p.getProduceTime());
        // 所有接口类型的引用变量都可直接赋给Object类型的变量
        Object obj = p;
    }
}

实现接口方法时,必须使用public修饰符

接口与抽象类之间的区别:

  • 接口只能有抽象方法、静态方法、默认方法、私有方法,不可以为普通方法提供实现;抽象类完全可以包含普通方法

  • 接口里只可以定义静态常量,不准出现普通成员变量;抽象类可以定义普通成员变量以及静态常量

  • 接口无构造函数,抽象可可以有

  • 接口里不包含初始化块,抽象类可以包含

  • 一个类最多有一个直接父类,包括抽象类,一个类可以实现多个接口

发布了189 篇原创文章 · 获赞 58 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/Coder_py/article/details/103983405