• 论Java中的抽象类与接口


    抽象类和抽象方法

    定义

    • 抽象方法和抽象类都必须被abstract关键字修饰。
    • 抽象——abstract,抽象类的方法不一定是抽象的,但抽象方法出现的类一定是抽象类。
    //抽象方法,没有方法体(即没有{}),只有声明
    abstract void f();
    
    • 最重要的是:抽象类,抽象既不是真的,所以,抽象类不可以实例化。但可以通过子类的实例化来使用
    /**
     * @author yhy
     * 用来完成9.2的练习
     * 验证抽象类与抽象方法的使用
     */
    public class YanZheng {
        public static void main(String[] args) {
    //      不能被实例化,抽象类,会报错
    //        ChouXiang chouxi = new ChouXiang() ;
    //        可以实例child类
    //        即通过继承其子类来实现不能继承抽象类
            Child test = new Child();
        }
    }
    abstract class AbstractChouXiang{
        /**
         * 构造函数
         */
        AbstractChouXiang() {
        }
        /**
         * 定义一个抽象类的抽象方法
         */
        abstract void chouxiang();
    }
    class Child extends AbstractChouXiang{
       Child(){
           System.out.println("实例时候就打印出来");
       }
    
        /**
         * 注意这里不是abstract就不要讲方法定义为abstract
         */
        @Override
        void  chouxiang(){
             System.out.println("继承抽象类");
    
        }
    }
    
    • 子类可以不是抽象类,但要实现抽象父类中的所有抽象方法,否则必须定义为abstract类型。(下面的代码中,我将其子类的重写方法注释掉之后,就会报错must be declared abstract or implentment abstract method)

    与普通类的区别以及注意点:

    • 抽象类也是可以与普通类那样,可以直接extends,区别在于抽象类不能直接实例化,可以通过实例化其子类,通过子类重写方法实现等——设置抽象方法就是让子类来实现的,否则毫无意义。

    • 与普通方法的区别

      抽象方法和空方法体的方法不是同一个概念。例如,public abstract void test();是一个抽象方法,它根本没方法体,即方法定义后面没有一对花括号;但public void test(){}方法是一个普通方法,它已经定义了方法体,只是方法体为空,即它的方法体什么也不做,因此这个方法不可使用abstract来修饰。——疯狂的Java讲义

    • abstract不能用于修饰Field,不能用于修饰局部变量,即没有抽象变量、没有抽象Field等说法;abstract也不能用于修饰构造器,没有抽象构造器,抽象类里定义的构造器只能是普通构造器

    抽象类的作用

    • 《thinking in java》

      • 抽象类是普通的类与接口之间的一种中庸之道。

      • 抽象方法、抽象类可以使类的抽象性明确起来,告诉用户和编译器怎么使用它们;

      • 同时,抽象类是很好的重构工具,在后期的工作中,可以实现重用性。

    • 体现一种模板的效果,从一群相似的子类提炼出一个抽象类的感觉一样,提供了一种规范,子类可以在其原来的基础上进行扩展。

    • 抽象父类可以只定义需要使用的某些方法,把不能实现的部分抽象成抽象方法,就是一中留给下一代去实现,一开始没有能力去实现,那可就给厉害的人去做,留给其子类去实现。

    接口

    定义

    • 特殊的“抽象类”——接口(interface):比抽象类更加抽象的是接口,在接口中所有的方法都是抽象的。就不能像上面的抽象类一样还可以有普通方法。
    //省略public就变为默认级别,只能在当前包所访问
    public interface Figure { 
    //接口中静态成员变量
    String name = "几何图形";//省略public static final 
    // 绘制几何图形方法
    void onDraw(); //省略public 这里是抽象方法
    }
    
    • Java中可以implements多个接口,多继承的含义便是接入多个接口(继承只能单继承)
    • 一个类可以实现一个或多个接口,继承使用extends关键字(但接口只能继承接口),实现则使用implements关键字。

    示例

    • JieKou.java
    import java.text.SimpleDateFormat;
    
    /**
     * @author yhy
     * 这个是实现接口定义的代码,在其它地方去调用
     * 这里的接口不用public的话,其它的包就访问不了
     */
    public interface JieKou {
    //   定义了两个常量
        /**
         * 这里定义一个df变量来获取当前时间
         */
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        String AUTHOR = "yhycoder";
        /**
         * 定义一个接口的方法
         * 这里的public是多余的,在接口里面是自动为public
         */
        /*public*/ void print();
    }
    
    
    • 使用接口的Java代码
    //访问了其它包的接口,就是下面这个地址
    import music.daima.ebook.JieKou;
    import java.util.Date;
    
    public class UseInterfaces {
        public static void main(String[] args) {
    //实例化using类,实现查看代码的运行情况
            Using Shuchu = new Using();
            Shuchu.print();
    
        }
    }
    
    /**
     * 这里是接口继承接口
     */
    interface Jiekou2 extends JieKou{
        String num = "接口2";
    }
    
    /**
     * 这里是Using类实现了JieKou和Jiekou2接口,逗号隔开
     */
    class Using implements JieKou,Jiekou2 {
        /**
         * 重写了方法,调用接口定义的常量
         */
        @Override
        public void print() {
            System.out.println(AUTHOR+"在新的包里面使用接口的时间:"+df.format(new Date())+" 同时还有"+num);
        }
    }
    
    

    注意

    1. 接口与抽象类一样都不能被实例化
    2. 实现接口时接口中原有的抽象方法在实现类中必须实现。默认方法可以根据需要有选择实现(覆盖)。静态方法不需要实现,实现类中不能拥有接口中的静态方法。(Java 8之后)
    //InterfaceA.java文件,定义一个接口 
    public interface InterfaceA {
    //抽象方法
        void methodA();
    	String methodB();
    // 默认方法
    	default int methodC() {
    	return "6666";
    	}
    // 默认方法
    	default String methodD() {
    	return "这是默认方法";
    	}
    // 静态方法
    	static double methodE() {
    	return 0.0;
    	} 
    }
    
    
    

    实现接口代码

    import xxxx.InterfaceA;
    public class ABC implements InterfaceA {
    	//重写
        @Override
    	public void methodA() {
    	}
    	@Override
    	public String methodB() {
    	return "实现methodB方法...";
    	}
        //重写覆盖,根据自己的需要来。
    	@Override
    	public int methodC() {
    	return 500;
    	} 
    }
    //实现类中不能有接口中的静态方法,最后一行
    public class HelloWorld {
    	public static void main(String[] args) {
    //声明接口类型,对象是实现类,发生多态
    	InterfaceA abc = new ABC();
    // 访问实现类methodB方法
    	System.out.println(abc.methodB());
    // 访问默认方法methodC
    	System.out.println(abc.methodC()); 
    // 访问默认方法methodD
    	System.out.println(abc.methodD()); 
    // 访问InterfaceA静态方法methodE,这里不能通过实现类去使用接口的静态方法,只能通过接口名调用
    	System.out.println(InterfaceA.methodE()); 
        } 
    }
    

    作用

    1. 规范,在分配不同人的任务时,接口就像是总纲一样,告诉大家去实现哪些功能模块等。(命名规范都有限制到)

    最后:接口与抽象类的异同

    不同

    • 接口interface,实现接口则使用implements;抽象类abstract

    • 抽象类可以有普通方法。Java 8 之前接口中只有抽象方法,而 Java 8 之后接口中也可以声明具体方法,具体方法通过声明默认方法实现。

    • 接口可以继承多个,而抽象类不可以。

    • 和类继承相似,子接口扩展某个父接口,将会获得父接口里定义的所有抽象方法、常量Field、内部类和枚举类定义。

    • 实现父接口的所有:一个类实现了一个或多个接口之后,这个类必须完全实现这些接口里所定义的全部抽象方法(也就是重写这些抽象方法);否则,该类将保留从父接口那里继承到的抽象方法,该类也必须定义成抽象类。

    • 接口定义的是一种规范,因此接口里不能包含构造器和初始化块定义。接口里可以包含Field(只能是常量)、方法(只能是抽象实例方法)、内部类(包括内部接口、枚举)定义。但抽象类与普通类一样,可以有构造器,初始化模块等。

    • 接口只有常量——接口中不能有实例成员变量,接口所声明的成员变量全部是静态常量,即便是变量不加 public static final 修饰符也是静态常量。抽象类与普通类一样各种形式的成员变量都可以声明。

    相同

    • 都不能直接实例化来使用。
    • 接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。

    使用场景

    • 想要多重继承的时候——接口(功能性强,规范性)

    • 想要底层基础功能模块不断改变——抽象类(模板设计)

    感谢

    才疏学浅,不对的地方多多指教!

    借鉴

    博客园的小伙伴

    也是园内小伙伴

  • 相关阅读:
    HDU 1166 敌兵布阵 (线段树 & 树状数组)
    HDU 1286 找新朋友 (欧拉函数)
    HDU 2203 亲和串 (KMP)
    HDU 1394 Minimum Inversion Number (归并排序 | 线段树 | 数状数组)
    HDU Leftmost Digit
    POJ 1195 Mobile phones
    C# 用jquery多个文件上传
    Ajax.NET Professional csharp DropDownList两级联无刷新绑定
    C# 公农历算法 ChineseLunisolarCalendar的一点思路
    csharp webform Button控件OnClick,OnClientClick事件
  • 原文地址:https://www.cnblogs.com/yhycoder/p/12186310.html
Copyright © 2020-2023  润新知