• java基础>接口和抽象类 小强斋


    抽象类和接口

    引入原因:

    1、为了能够向上转型为多个基类(由此带来灵活性)

    2、防止使用者创建对象

    一、抽象类

    抽象方法:只声明而未定义方法体的方法称为抽象方法,抽象方法必须使用abstract关键字声明。

    抽象类:   abstract修饰的类是抽象类,抽象类必须使用abstract关键字进行声明。 抽象类通常包含抽象方法。

    说明:

    1、抽象类不能直接实例化。编译器报错Cannot instantiate the type

    2、如果从一个抽象类继承,并想创建新类的对象,必须为基类中的所有抽象方法提供方法定义,如果不这样做,那么子类也必须声明成抽象类。即包含抽象方法的类必须被声明为抽象类,否则编译器会报错。

    3抽象类也可以不包含抽象方法。

    4、抽象类中能有构造方法吗?可以

    可以存在,而且依然符合于子类对象的实例化过程的要求。

    abstract class Demo { // 抽象类
    
    	public Demo() {
    		System.out.println("抽象类中的构造方法!");
    	}
    
    	public void print() {
    		System.out.println("Hello  World!!!");
    	}
    
    	public abstract void fun(); // 抽象方法
    
    };
    
    class DemoImpl extends Demo {
    
    	public DemoImpl() {
    		super();
    		System.out.println("子类中的构造方法!");
    
    	}
    
    	public void fun() {}
    
    };
    
    public class AbsDemo03 {
    
    	public static void main(String args[]) {
    		DemoImpl di = new DemoImpl();
    		di.print();
    
    	}
    
    };

    抽象类和普通类相比,只是增加了抽象abstract class的声明,和增加了抽象方法而已。

    范例:定义一个抽象类

    abstract class Demo { // 抽象类
    
    	public void print() {
    		System.out.println("Hello World!!!");
    	}
    	public abstract void fun(); // 抽象方法
    
    };

    二、接口

    当一个类中全部是由抽象方法和全局常量组成的时候,那么就可以将这个类定义成一个接口了, interface关键字产生一个完全抽象的类。接口被用来建立类与类之间的协议。

    范例:定义接口

    interface Demo{  // 接口
    
             public static final String INFO =  "hello world" ;
    
             public abstract void print() ;
    
             public abstract void fun() ;
    
    }
    

    一个接口定义完成之后,实际上与抽象类的使用原则是一样的:

    1、  接口必须有子类,子类(如果不是抽象类)则必须覆写接口中的全部抽象方法;

    2、  接口是不能直接进行对象的实例化操作。

    3、  接口的访问权限和类相同。

    4、  一个子类可以同时继承(实现)多个接口

    5、 一个子类如果要实现接口又要继承类的话,则必须先继承类,再实现接口.即extends要写在implements的前面。

    6、接口中的成员隐含是static和final的

    接口中的全部组成都是抽象方法和全局常量的话,因此以下的两种定义接口的形式是完全一样的:

    interface Demo{  //接口
    
              public static final String INFO =  "hello  world" ;
    
              public abstractvoid print() ;
    
    }


     

    interface Demo{  //接口
    
              String INFO = "hello world"  ;
    
              void print() ;
    
    }

    所有的修饰符在接口中是否添加本身是没有任何意义的,而且接口中的方法全部都属于公共的方法操作(public)。

    7、一个接口可以同时通过extends关键字继承多个接口。

    interface A{
    
     
    
             public void printA() ;
    
     
    
    }
    
     
    
    interface B{
    
     
    
             public void printB() ;
    
     
    
    }
    
     
    
    interface C  extends A,B{
    
     
    
             public void printC() ;
    
     
    
    }
    
     
    
    class Demo  implements C {
    
     
    
             public void printA(){}
    
     
    
             public void printB(){}
    
     
    
             public void printC(){}
    
     
    
    };

    三、抽象类的使用——模板设计

         例如:现在可以将一个人的划分成学生和工人。

    ·不管是工人还是学生肯定都有其共同的属性,例如:姓名、年龄。

    ·但是,既然是一个类,肯定就拥有自己的信息,例如:学生有学校,工人有工作。

    abstract class Person {
    
            private String name ;
    
            private int age ;
    
            public Person(String name,int age){
    
                      this.name = name ;
    
                      this.age = age ;
    
            }
    
            public void say(){
    
                      System.out.println(this.getContent()) ;     
    
            }
    
            public abstract String getContent() ;
    
            public String getName(){
    
                      return this.name ;
    
            }
    
            public int getAge(){
    
                      return this.age ;
    
            }
    
    };
    
    class Student extends Person {
    
            private String school ;
    
            public Student(String name,int age,String school){
    
                      super(name,age) ;
    
                      this.school = school ;
    
            }
    
            public String getContent(){
    
                      return this.toString() ;
    
            }
    
            public String toString(){
    
                      return "姓名:" + super.getName() + ",年龄:" + super.getAge() + "学校:" + this.school ;
    
            }
    
    };
    
    class Worker extends Person {
    
            private String job ;
    
            public Worker(String name,int age,String job){
    
                      super(name,age) ;
    
                      this.job = job ;
    
            }
    
            public String getContent(){
    
                      return this.toString() ;
    
            }
    
            public String toString(){
    
                      return "姓名:" + super.getName() + ",年龄:" + super.getAge() + "工作:" + this.job ;
    
            }
    
    };
    
    public class CaseDemo02 {
    
            public static void main(String args[]){
    
                      // Person per = new Student("张三",20,"清华大学") ;
    
                      Person per = new Worker("张三",20,"经理") ;
    
                      per.say() ;
    
            }
    
    };

    在实际的开发中,所有的类永远不要去继承一个已经实现好的类,而只能继承抽象类或实现接口。

    四、接口的使用——制定标准

    接口主要有以下三大使用 1、制定标准;2、表示能力;3、将远程方法的操作视图暴露给客户端。

    电脑上有USB接口,只要是USB设备都可以向电脑上插入并使用

    interface USB{    // 定义好了一个标准
    
             public void use() ;                  // 使用
    
    }
    
    class Computer {
    
             public static void plugIn(USB usb){
    
                       usb.use() ;
    
             }
    
    };
    
    class Flash implements USB {
    
             public void use(){
    
                       System.out.println("使用U盘。") ;
    
             }
    
    };
    
    class Print implements USB {
    
             private String name ;
    
             public Print(String name){
    
                       this.name = name ;
    
             }
    
             public void use(){
    
                       System.out.println("欢迎使用" + this.name + "牌打印机!") ;
    
                       System.out.println("开始打印!") ;
    
             }
    
    };
    
    public class CaseDemo04 {
    
             public static void main(String args[]){
    
                       Computer.plugIn(new Flash());
    
                       Computer.plugIn(newPrint("HP")) ;
    
             }
    
    };
    

     

    五、接口的使用——工厂设计模式

    下面先来观察以下的一段代码:

    interface Fruit{
    
            public void eat() ;          
    
    }
    
    class Apple implements Fruit {
    
            public void eat(){
    
                      System.out.println("吃苹果。") ;
    
            }
    
    };
    
    class Orange implements Fruit {
    
            public void eat(){
    
                      System.out.println("吃橘子。") ;
    
            }
    
    };
    
    public class CaseDemo05 {
    
            public static void main(String args[]){
    
                      Fruit f = new Orange() ;
    
                      f.eat() ;
    
            }
    
    };
    

    以上代码中存在的问题:现在的程序中可以发现,在主方法(客户端)上,是通过关键字new直接为接口进行实例化,也就是说以后在使用的时候如果要不更改主方法的话,则主方法中永远只能使用一个类,这样的耦合度太深了。

    interface Fruit{
    
            public void eat() ;          
    
    }
    
    class Apple implements Fruit {
    
            public void eat(){
    
                      System.out.println("吃苹果。") ;
    
            }
    
    };
    
    class Orange implements Fruit {
    
            public void eat(){
    
                      System.out.println("吃橘子。") ;
    
            }
    
    };
    
    class Factory {
    
            public static Fruit getInstance(String className){
    
                      Fruit f = null ;
    
                      if("apple".equals(className)){
    
                               f = new Apple() ;
    
                      }
    
                      if("orange".equals(className)){
    
                               f = new Orange() ;
    
                      }
    
                      return f ;
    
            }
    
    };
    
    public class CaseDemo06 {
    
            public static void main(String args[]){
    
                      Fruit f = Factory.getInstance(args[0]) ;
    
                      f.eat() ;
    
            }
    
    };
    

    此时,中间加入了一个过渡端(Factory),那么都通过过渡端找到接口的实例,这样的设计称为工厂设计,以后扩充子类的时候修改工厂即可:即:某一局部的修改不影响其他环境。

    六、接口的使用——代理设计模式

    代理:继承和组合的中庸之道。将一个成员对象置于要构造的类中(就像组合),与此同时在新类中暴露了该类成员所有的方法(就像继承)。类的复用-代理

    一个代理人员可以代表一个真实的操作人员进行某些操作,但是两者的核心目的就是讨债。

     
    interface Subject{
    
            public void give() ;
    
    }
    
    class RealSubject implements Subject{
    
            public void give(){
    
                      System.out.println("真正的讨债者:还我的钱。") ;
    
            }
    
    };
    
    class ProxySubject implements Subject {
    
            private Subject sub ;     // 设置代理人
    
            public ProxySubject(Subject sub){
    
                      this.sub = sub ;
    
            }
    
            public void before(){
    
                      System.out.println("准备刀子,绳索,毒药。。。") ;
    
            }
    
            public void give(){
    
                      this.before() ;
    
                      this.sub.give() ;   // 真实主题
    
                      this.after() ;
    
            }
    
            public void after(){
    
                      System.out.println("跑路了。。。") ;
    
            }
    
    };
    
    public class CaseDemo07 {
    
            public static void main(String args[]){
    
                      Subject s = new ProxySubject(new RealSubject()) ;
    
                      s.give() ;
    
            }
    
    };
    

    在此设计之中可以发现,真实主题完成具体的业务操作,而代理主题将完成与真实主题有关的其他的操作。现在的IDE都能自动生成代理。

    七、接口的使用——适配器设计

    在正常情况下,一个接口的子类肯定是要覆写一个接口中的全部抽象方法。

    那么有没有一种可能性,通过代码的变更,让一个子类可以有选择性的来覆写自己所需要的抽象方法呢?

    从概念上讲这样肯定不合适,所以中间就想一想加入一个过渡端,但是这个过渡端又不能直接使用。

    interface Fun{
    
            public void printA() ;
    
            public void printB() ;
    
            public void printC() ;
    
    }
    
    abstract class FunAdapter implements Fun {
    
            public void printA(){}//空实现
    
            public void printB(){}
    
            public void printC(){}
    
    };
    
    class Demo extends FunAdapter {
    
            public void printA(){
    
                      System.out.println("Hello World!!!") ;
    
            }
    
    };
    

    一般在进行图形界面的开发中才会使用到适配器的设计思路。

    八、抽象类和接口的区别

            接口和抽象类从使用上看非常的相似,那么下面通过以下的表格对两者进行区分 

    No.

    比较

    抽象类

    接口

    1

    关键字

    使用abstract class声明

    使用interface声明

    2

    定义

    包含一个抽象方法的类

    抽象方法和全局常量的集合

    3

    组成

    属性、方法、构造、常量、抽象方法

    全局常量、抽象方法

    4

    权限

    抽象方法的权限可以任意

    只能是public权限

    5

    使用

    通过extends关键字继承抽象类

    通过implements关键字实现接口

    6

    局限

    抽象类存在单继承局限

    没有此局限,一个子类可以实现多个接口

    7

    顺序

    一个子类只能先继承抽象类再实现多个接口

    8

    实际作用

    只能做一个模板使用

    作为标准、表示能力

    9

    使用

    两者没有什么本质的区别,但是从实际上来看,如果一个程序中抽象类和接口都可以使用的话,则一定要优先考虑接口,因为接口可以避免单继承所带来的局限。

    10

    实例化

    都是依靠对象多态性,通过子类进行对象实例化的

     

  • 相关阅读:
    机器学习个人总结
    yolo buffer is too small for requested array
    anaconda + VSCode + 生产环境配置
    YOLO.h5 下载
    通过爬虫程序深入浅出java 主从工作模型
    KafKa记录
    springboot 整合spark-sql报错
    机器学习项目笔记
    python学习笔记之入门
    django-5-使用数据库
  • 原文地址:https://www.cnblogs.com/xiaoqiangzhaitai/p/5637614.html
Copyright © 2020-2023  润新知