zoukankan      html  css  js  c++  java
  • Java 接口和抽象类

    接口

    概念

    Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。

    特点

    • 在接口中声明的方法默认是抽象的(即只有方法标识符,而没有方法体)。
    • 抽象方法只能存在于抽象类或者接口中,但抽象类中却能存在非抽象方法,即有方法体的方法。接口是百分之百的抽象类。
    • 不能直接实例化一个接口,因为接口中的方法都是抽象的,没有方法体,但是,我们可以使用接口类型的引用指向一个实现了该接口的对象,并且可以调用这个接口中的方法。
    • 一个类可以实现多个接口。
    • 一个接口可以继承于另一个接口,或者另一些接口,接口也可以继承,并且可以多继承。
    • 一个类如果要实现某个接口的话,那么它必须要实现这个接口中的所有方法。
    • 接口中所有的方法都是public abstract 的,所有的属性都是public static final的。
    • 接口用来弥补类无法实现多继承的局限。
    • 接口也可以用来实现解耦。

     

    语法实现

    为了声明一个接口,我们使用interface关键字,在接口中的所有方法都必须只声明方法标识,而不声明具体的方法体,因为具体的方法体的实现是由实现该接口的类完成,使用implments实现接口。接口中的默认属性为Public Static Final。一个类实现这个接口必须实现这个接口中定义的所有的抽象方法。

    一个简单的接口:拥有全局变量和抽象方法。

    抽象类

    概念

    普通类是一个完善的功能类,可以直接产生实例化对象,并且在普通类中可以包含有构造方法、普通方法、static方法、常量和变量等内容。而抽象类是指在普通类的结构里面增加抽象方法的组成部分。那么什么叫抽象方法呢?在所有的普通方法上面都会有一个“{}”,这个表示方法体,有方法体的方法一定可以被对象直接使用。而抽象方法,是指没有方法体的方法,同时抽象方法还必须使用关键字abstract做修饰。而拥有抽象方法的类就是抽象类,抽象类要使用abstract关键字声明。

    特点

    • 抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;
    • 抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理;
    • 抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类;
    • 子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为abstract类);
    • 由于抽象类里会存在一些属性,那么抽象类中一定存在构造方法,其存在目的是为了属性的初始化。并且子类对象实例化的时候,依然满足先执行父类构造,再执行子类构造的顺序。
    • 抽象类不能用final声明,因为抽象类必须有子类,而final定义的类不能有子类;
    • 外部抽象类不允许使用static声明,而内部的抽象类允许使用static声明。使用static声明的内部抽象类相当于一个外部抽象类,继承的时候使用“外部类.内部类”的形式表示类名称。
    • 任何时候,如果要执行类中的static方法的时候,都可以在没有对象的情况下直接调用,对于抽象类也一样。

    【范例】

    定义接口格式
    [public]interface 接口名称 [extends父接口名列表]
    {
    //静态常量
    [public] [static] [final] 数据类型变量名=常量值;
    
    //抽象方法
    [public] [abstract] [native] 返回值类型方法名(参数列表);
    
    }
    
    实现接口格式:
    
    [修饰符] class 类名[extends 父类名] [implements 接口A,接口B,···]
    {
    类成员变量和成员方法;
    为接口A中的所有方法编写方法体,实现接口A;
    为接口B中的所有方法编写方法体,实现接口B;
    
    }
    具体实例
    //简单接口
    interface demoA{
          //全局变量用默认用public static final修饰
           final int a=6;
          //抽象方法默认用 public abstract 修饰
           void show();
    }
    //接口实现
    class testDemoB implements demoA{
           //实现接口中所以抽象方法
           public void show(){
             System.out.println("欢迎你");
       }
    }

    接口和抽象类的区别

    接口和抽象类最大的区别,就在于Java抽象类可以提供某些方法的部分实现,而Java接口不可以,这大概就是Java抽象类唯一的优点吧,但这个优点非常有用。如果向一个抽象类里加入一个新的具体方法时,那么它所有的子类都一下子都得到了这个新方法,而Java接口做不到这一点,如果向一个Java接口里加入一个新方法,所有实现这个接口的类就无法成功通过编译了,因为你必须让每一个类都再实现这个方法才行,这显然是Java接口的缺点。
    一个抽象类的实现只能由这个抽象类的子类给出,也就是说,这个实现处在抽象类所定义出的继承的等级结构中,而由于Java语言的单继承性,所以抽象类作为类型定义工具的效能大打折扣。在这一点上,Java接口的优势就出来了,任何一个实现了一个Java接口所规定的方法的类都可以具有这个接口的类型,而一个类可以实现任意多个Java接口,从而这个类就有了多种类型。
    不难看出,Java接口是定义混合类型的理想工具,混合类表明一个类不仅仅具有某个主类型的行为,而且具有其他的次要行为。
     
    在语法上,抽象类和接口有着以下不同:
    1.abstract class在Java语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface。 继承抽象类使用的是extends关键字,实现接口使用的是implements关键字,继承写在前面,实现接口写在后面。如果实现多个接口,中间用逗号分隔。
    例:
    public class Main extends JApplet
    public class Main implements Runnable
    public class Main extends JApplet implements ActionListener
    public class Main extends JApplet implements ActionListener, Runnable
    2.在abstract class中可以有自己的数据成员,也可以有非abstract的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在 interface中一般不定义数据成员),所有的成员方法都是abstract的。
    3.abstract class和interface所反映出的设计理念不同。其实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系。
    4.实现接口的类必须实现其中的所有方法,继承自抽象类的子类实现所有的抽象方法。抽象类中可以有非抽象方法。接口中则不能有实现方法。
    5.接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。
    6.抽象类中的变量默认具有 friendly权限,其值可以在子类中重新定义,也可以重新赋值。
    7.接口中的方法默认都是 public abstract 类型的。
     
    拓展:

    转型是在继承的场景下的用法。
    向上转型:子类对象转为父类,父类可以是接口。公式:Father f = new Son();Father是父类或接口,son是子类。向上转型不用强制转型。
    向下转型:父类对象转为子类(为了将向上转型的对象还原)。

    公式:

    Father f;
    Son s = (Son)f;

     

    向上转型

    向上转型后父类的引用所指向的属性是父类的属性,如果子类重写了父类的方法,那么父类引用指向的或者调用的方法是子类的方法,这个叫动态绑定。

    public class Animal {
        public void eat(){
            System.out.println("animal");
        }
    }
    
    public class Cat extends Animal{
        public void eat(){
            System.out.println("Cats");
        }
        public void run(){
            System.out.println("run");
        }
    }
    public class Main {
        public static void main(String[] args) {
            Animal animal = new Cat(); //向上转型
            animal.eat(); // Cats
            // 向上转型后父类引用不能调用子类自己的方法, 调用run方法会报错
            animal.run();
        }
    }

    向上转型的作用,减少重复代码,父类为参数,调有时用子类作为参数,就是利用了向上转型。这样使代码变得简洁。

    public void eat(Animal animal){
        animal.eat();
    }
    // 所有继承animal的都可以调用
    eat(new Dog());
    eat(new Cat());

    向上转型后无法调用子类原本的特有的方法和属性,为此这里引入向下转型来还原。

    向下转型

    向下转型的前提是父类对象指向的是子类对象(也就是说,在向下转型之前,它得先向上转型)。

    Animal a = new Cat();
    Cat c = ((Cat) a);
    // 以下代码会报错
    Animal a1 = new Animal();
    Cat c1 = ((Cat) a1);

    所以向下转型前要先用instanceof进行判断。

    注意:

    1.类与类之间的关系为继承,只能单继承,但可以多层继承。

    2.类与接口之间的关系为实现,既可以单实现,也可以多实现。

    3.接口与接口之间的关系为继承,既可以单继承,也可以多继承。

    参考来源:https://blog.csdn.net/sysuzhyupeng/article/details/84890147

  • 相关阅读:
    python json 和 pickle的补充 hashlib configparser logging
    go 流程语句 if goto for swich
    go array slice map make new操作
    go 基础
    块级元素 行内元素 空元素
    咽炎就医用药(慢性肥厚性咽炎)
    春季感冒是风寒还是风热(转的文章)
    秋季感冒 咳嗽 怎么选药
    解决IE浏览器“无法显示此网页”的问题
    常用的 css 样式 记录
  • 原文地址:https://www.cnblogs.com/lucky1024/p/11535460.html
Copyright © 2011-2022 走看看