• Java入门系列-18-抽象类和接口


    抽象类

    在第16节继承中,有父类 People

    People people=new People();
    people.sayHi();
    

    实例化People是没有意义的,因为“人”是一个抽象的概念。

    怎么才能避免父类的实例化呢?使用 abstract 关键字修饰类(抽象类)。

    抽象父类

    public abstract class People {
    	private String name;
    	
    	public People(String name) {
    		super();
    		this.name = name;
    	}
    
    	//人类共有方法 哭
    	public void cry() {
    		System.out.println("呜呜");
    	}
    	//抽象方法 不做具体实现
    	public abstract void sayHi();
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    }
    

    子类:Chinese.java

    //中国人
    public class Chinese extends People{
    
    	public Chinese(String name) {
    		super(name);
    	}
    
    	//必须实现
    	@Override
    	public void sayHi() {
    		System.out.println(this.getName()+":你好!");
    	}
    }
    

    子类:Britisher.java

    //英国人
    public class Britisher extends People{
    
    	public Britisher(String name) {
    		super(name);
    	}
    
    	@Override
    	public void sayHi() {
    		System.out.println(this.getName()+":Hello!");
    	}
    }
    

    测试类

    public class TestPeople {
    
    	public static void main(String[] args) {
    		//People people=new People("张三");//去掉注释试试
    		People chinese=new Chinese("张三");
    		chinese.sayHi();
    		People britisher=new Britisher("John");
    		britisher.sayHi();
    	}
    }
    

    被关键字 abstract 修饰的类是抽象类,抽象类不能实例化

    被关键字 abstract 修饰的方法是抽象方法,抽象方法没有方法体

    抽象方法必须在抽象类里

    抽象方法必须在子类中被实现,除非子类是抽象类

    抽象方法没有方法体
    public abstract void sayHi();

    注意:被 abstract 修饰后不能使用 final 修饰!

    接口

    如何实现防盗门这个类?门有“开”和“关”的功能,锁有“上锁”和“开锁”的功能,将门和锁分别定义为抽象类。但是防盗门可以继承门的同时又继承锁吗?不能,防盗门不是锁,不符合 is a 的关系而且Java只支持单继承。

    接口的语法

    public interface MyInterface {
    	public abstract void foo();
    }
    

    接口可以认为是纯粹的抽象类

    接口中的方法都是抽象方法 (public abstract)

    接口不可以被实例化

    实现类必须实现接口中的所有方法

    接口中的变量都是静态常量

    接口之间可以互相继承(extedns),类只能实现接口(implements)

    一个类可以继承一个父类,实现多个接口

    演示接口的继承及实现接口

    父接口:A.java

    public interface A {
    	void methodA();
    }
    

    子接口:B.java

    public interface B extends A{
    	void methodB();
    }
    

    接口的实现类:C.java

    public class C implements B{
    
    	@Override
    	public void methodA() {
    	}
    
    	@Override
    	public void methodB() {
    	}
    }
    

    接口表示能力

    面向接口编程时,关心实现类有何能力,而不关心实现细节。面向接口的约定而不考虑接口的具体实现。

    在鸟类中,白鹭可以飞,鸵鸟不能飞,所以在这里飞是一种能力,下面看一下代码的设计。

    飞行接口:Fly.java

    //表示飞行能力
    public interface Fly {
    	/**
    	 * 飞行
    	 */
    	public abstract void fly();
    }
    

    游泳接口:Swim.java

    //表示游泳能力
    public interface Swim {
    	public abstract void swim();
    }
    

    鸟类:Bird.java

    //抽象鸟类 重用代码
    public abstract class Bird {
    	/**
    	 * 下蛋
    	 */
    	public void layEggs() {
    		System.out.println("产出一枚蛋");
    	}
    }
    

    白鹭类:Egret.java

    //白鹭类
    public class Egret extends Bird implements Fly,Swim{
    
    	@Override
    	public void fly() {
    		System.out.println("使劲煽动翅膀后起飞");
    	}
    
    	@Override
    	public void swim() {
    		System.out.println("漂在了水面上,轻松的游来游去");
    	}
    }
    

    鸵鸟类:Ostrich.java

    //鸵鸟类
    public class Ostrich extends Bird implements Swim{
    
    	@Override
    	public void swim() {
    		System.out.println("漂在了水面了,开始游动");
    	}
    }
    

    测试类

    public class TestBird {
    	public static void main(String[] args) {
    		Egret egret=new Egret();
    		egret.swim();
    		egret.fly();
    		Ostrich ostrich=new Ostrich();
    		ostrich.swim();
    	}
    }
    

    接口表示约定

    在生活中,我们使用的插座,规定了两个接头剪得额定电压、两个接头间的距离、接头的形状。

    在代码中约定体现在接口名称和注释上

    下面使用面向接口编程实现一台计算机的组装,计算机的组成部分有:CPU、硬盘、内存。

    先创建 CPU、硬盘、内存接口

    package computer;
    
    /**
     * CPU 接口
     * @author Jack
     *
     */
    public interface CPU {
    	/**
    	 * 获取CPU品牌
    	 * @return
    	 */
    	String getBrand();
    	
    	/**
    	 * 获取CPU主频
    	 * @return
    	 */
    	Float getFrequency();
    }
    
    package computer;
    
    /**
     * 硬盘接口
     * @author Jack
     *
     */
    public interface HardDisk {
    	
    	/**
    	 * 获取硬盘容量
    	 * @return
    	 */
    	int getCapacity();
    }
    
    package computer;
    
    /**
     * 内存接口
     * @author Jack
     *
     */
    public interface EMS {
    	/**
    	 * 获取内存容量
    	 * @return
    	 */
    	int getSize();
    }
    

    将接口设计到计算机类中

    package computer;
    /**
     * 计算机类
     * @author Jack
     *
     */
    public class Computer {
    	private CPU cpu;//cpu接口
    	private HardDisk hardDisk;//硬盘接口
    	private EMS ems;//内存接口
    
    	public Computer() {
    	}
    
    	public Computer(CPU cpu, HardDisk hardDisk, EMS ems) {
    		super();
    		this.cpu = cpu;
    		this.hardDisk = hardDisk;
    		this.ems = ems;
    	}
    
    	public CPU getCpu() {
    		return cpu;
    	}
    
    	public void setCpu(CPU cpu) {
    		this.cpu = cpu;
    	}
    
    	public HardDisk getHardDisk() {
    		return hardDisk;
    	}
    
    	public void setHardDisk(HardDisk hardDisk) {
    		this.hardDisk = hardDisk;
    	}
    
    	public EMS getEms() {
    		return ems;
    	}
    
    	public void setEms(EMS ems) {
    		this.ems = ems;
    	}
    }
    

    创建 CPU、硬盘、内存接口的实现

    package computer.impl;
    
    import computer.CPU;
    
    /**
     * 英特尔 CPU
     * @author Jack
     *
     */
    public class IntelCPU implements CPU{
    
    	@Override
    	public String getBrand() {
    		return "英特尔";
    	}
    
    	@Override
    	public Float getFrequency() {
    		return 2.3f;
    	}
    }
    
    package computer.impl;
    
    import computer.HardDisk;
    
    /**
     * 闪迪硬盘
     * @author Jack
     *
     */
    public class SanDisk implements HardDisk{
    
    	@Override
    	public int getCapacity() {
    		return 3000;
    	}
    }
    
    package computer.impl;
    
    import computer.EMS;
    
    /**
     * 金士顿 内存
     * @author Jack
     *
     */
    public class JSDEMS implements EMS{
    
    	@Override
    	public int getSize() {
    		return 4;
    	}
    }
    

    完成计算机及组件的组装进行测试

    package computer;
    
    import computer.impl.IntelCPU;
    import computer.impl.JSDEMS;
    import computer.impl.SanDisk;
    
    public class TestComputer {
    	public static void main(String[] args) {
    		CPU cpu=new IntelCPU();//创建CPU
    		HardDisk sanDisk=new SanDisk();//创建硬盘
    		EMS jsdEMS=new JSDEMS();//创建内存
    		Computer computer=new Computer(cpu,sanDisk,jsdEMS);
    		System.out.println("CPU型号:"+computer.getCpu().getBrand());
    		System.out.println("硬盘容量:"+computer.getHardDisk().getCapacity()+" GB");
    		System.out.println("内存容量:"+computer.getEms().getSize()+" GB");
    	}
    }
    

    接口总结

    接口有比抽象类更好的特性:
    1.可以被多继承
    2.设计和实现完全分离
    3.更自然的使用多态
    4.更容易搭建程序框架
    5.更容易更换实现

    搜索关注公众号「享智同行」,第一时间获取技术干货

  • 相关阅读:
    Arch 真好用
    Spring 自定义注解-字段注解
    Raft论文概述
    Raft成员变化(Membership Change)
    Reactor模式详解
    高性能IO之Reactor模式
    WinFrm中多线程操作窗体属性
    Reactor模式
    高并发中的线程与线程池
    二层交换机与三层交换机区别详解!
  • 原文地址:https://www.cnblogs.com/AIThink/p/9831291.html
Copyright © 2020-2023  润新知