抽象类和接口的区别


  

1 抽象类

1.1 为什么定义抽象类

  把一组小猫抽象为Cat类,把一组小狗抽象为Dog类, 把人抽象为Person类, 把小狗/小猫/人可以进一步抽象为动物类
  就像动物类/交通工具类/食物类等等这些类没法具体化, 这些类就可以定义为抽象类, 对事物进行更高层级的抽象可以形成更抽象的类

1.2 如何定义抽象类

  使用abstract修饰的类就是抽象类

1.3 抽象类的特点

  1)抽象类不能实例化对象, 抽象类引用需要赋值子类对象
  2)含有抽象方法的类必须定义为抽象类, 但是抽象类中不一定含有抽象方法
  3)子类继承了抽象类后, 需要重写抽象类的所有抽象方法,如果子类没有重写所有的抽象方法,子类也需要定义为抽象类
  4)abstract与final 不可以共存
  5)抽象类的引用可以赋值匿名内部类对象

1.4 为什么需要定义抽象方法

  当一个类的某个操作不能具体实现时, 在不同子类中有不同的实现方式,这个操作就可以定义为抽象方法

1.5 如何定义抽象方法

使用abstract修饰方法, 只有方法的声明部分,没有方法体
abstract  class  Animal{
	public abstract void move();
}
/**
 * 定义一个宠物类Pet, 宠物会卖萌sellMeng()
 * 	不同各类的宠物,卖萌的方式不同, 宠物类有卖萌的行为不能具体实现
 *  ,这个行为可以定义为抽象方法
 *
 */
public abstract class Pet {

	public abstract void sellMeng();  		
	//使用abstract修饰, 只有方法的声明,没有方法体
}
//定义小猫类
class Cat extends Pet {

	@Override
	public void sellMeng() {
		System.out.println("小猫喵喵喵~~~~");
	}
}
//定义小狗Dog类继承Pet类, 重写卖萌方法
class Dog extends Pet {

	@Override
	public void sellMeng() {
		System.out.println("小狗旺旺~~~~~");
	}
}

//定义主人类Master,  
//主人有一个喂养宠物的方法,主人喂宠物时,宠物就卖萌
public class Master {

	public void feed( Pet pet) {
		pet.sellMeng();
	}
}
/**
 * 编写测试类, 主人喂狗, 主人喂猫
 */
public class Test {

	public static void main(String[] args) {
		Master lisi = new Master();		
		Dog dahuang = new Dog();		
		//feed(Pet)形参是父类的引用, 在调用方法时,传递子类对象
		lisi.feed(dahuang);
		
		lisi.feed( new  Cat() );
		
		//feed()方法的形参是抽象类的引用, 还可以传递匿名内部类对象
		lisi.feed( new Pet() {
			//在匿名内部类中重写抽象类的抽象方法
			@Override
			public void sellMeng() {
				System.out.println("哼哼哼~~~~~");
			}
		});
	}

}

2 接口

2.1 接口是什么

  电脑上的接口有哪些?
  USB接口 , 网线接口, 耳机接口, VGA接口, HDMI高清接口, 电源接口, Thunder接口
  电脑通过这些接口连接更多的外设,扩展了电脑的功能

Java中的接口就是功能的封装
Java中的类通过接口可以扩展类的功能

2.1 如何定义接口

  语法:

[修饰符]  interface    接口名 {
 	功能,使用方法描述, 接口中的 方法默认使用public abstract修饰
}

2.3 如何使用接口

class  类名   implements  接口名 {
	类需要重写接口中的抽象方法
}

2.4 接口的内容

/**
 * 接口的内容
 *
 */
public interface MyInterface {
	void  m1(); 		//默认使用public abstract修饰, 需要在实现类中重写
	
	int xx = 666; 		//字段默认使用public static final修饰, 直接通过接口名访问
	
	public static void sm() {
		System.out.println("接口 中可以定义静态方法, 直接使用接口名调用");
	}
	
	public default void m2() {
		System.out.println("在接口中使用default修饰方法, 表示该方法可以有默认的方法体"
				+ "该方法在实现类中可以重写,也可以不重写");
	}
}

2.5 接口的特点

  1)类实现了接口,需要重写接口中抽象方法,如果没有重写接口所有的抽象方法,那么这个类需要定义为抽象类
  2)接口是一种引用数据类型,可以定义变量,但是接口不能实例化对象, 接口的引用可以赋值实现类对象, 通过接口引用调用抽象方法,实际上就是执行实现类对象的方法,称为接口多态 . 接口就是为了实现多态的
  3)接口的内容: 接口中方法默认使用 public abstract 修饰, 接口中的字段默认使用public static final 修饰, 接口中还可以定义 public static 方法, 还可以定义 public default 方法
  4)一个类在继承父类的同时,可以实现多个接口, 接口支持多实现, 需要重写所有接口的所有抽象方法
  5)接口也可以继承, 并且支持多继承
  6) 接口的引用可以赋值匿名内部类对象

/**
 * 定义一个飞行接口Flyable
 */
public interface Flyable {
	//封装飞行功能
	void fly(); 			//接口中的方法默认使用public abstract修饰
}
/**
 * 定义Bird鸟类, 
 * 		实现了Flyable接口, 需要重写接口的抽象方法
 *
 */
public class Bird implements Flyable {
	//Bird类重写了抽象方法,具有了接口中指定的功能
	@Override
	public void fly() {
		System.out.println("小鸟使用小翅膀可以在天上飞");
	}
}
public class Plane implements Flyable {

	@Override
	public void fly() {
		System.out.println("飞机也能飞");
	}
}
/**
 * 测试接口多态
 */
public class Test01 {

	public static void main(String[] args) {
		//1) 接口是一种引用数据类型, 接口可以定义变量
		Flyable f;
		//2)接口不能实例化对象
//		f = new Flyable();
		//3)给接口引用赋值实现类对象
		f = new Bird();
		//4) 通过接口引用调用抽象方法,实际上执行的是实现类对象的方法, 接口多态 
		f.fly();
		//接口就是为了实现多态
		f = new Plane();
		f.fly();
		
		//5)接口引用可以赋值匿名内部类对象
		f = new Flyable() {
			//在匿名内部类中重写接口的抽象方法
			@Override
			public void fly() {
				System.out.println("蝴蝶也能飞");
			}
		};
		f.fly();
	}
}

接口支持多继承

//定义吃饭的接口
public interface Eatable {
	void eat();
}
//定义睡觉的接口
public interface Sleepable {
	void sleep();
}
//接口支持多继承
public interface Supermanble extends Flyable, Eatable, Sleepable {
	/*
	 * 现在Supermanble接口从Flyable接口中继承了fly()方法, 
	 * 从Eatable接口中继承了eat()方法
	 * 从Sleepable接口中继承了sleep()方法
	 * 在子接口中,可以添加特有的方法
	 */
	void  fight();
}

/**
 * 一个类,可以实现多个接口, 接口名之间使用逗号分隔
 * 		类实现了 多个接口,  需要重写所有接口的所有抽象方法
 *
 */
public class Person implements Eatable, Sleepable, Flyable {

	@Override
	public void fly() {
	}

	@Override
	public void sleep() {
	}

	@Override
	public void eat() {
	}
}

3 接口与抽象类的异同点

相同点:
  1)都可以定义抽象方法
  2)都不能实例化对象
  3)抽象方法都需要被重写(覆盖)
不同点:
  1)意义不同
  接口是功能的封装
  抽象类是事物更高层级的抽象
  2)定义方式不同
  接口使用interface
  抽象类使用 abstract class
  3)内容不同
  接口中内容有四部分(JDK8): 默认的public abstract方法, 默认的public static final常量, 还可以定义public static 方法, public default方法
  抽象类中除了抽象方法外, 普通类有的所有成员都可以在抽象类中定义, 如实例方法/实例变量/ 静态方法/静态变量/构造方法
  4)使用方式不同
  接口需要被类implements实现
  抽象类需要被类extends继承
  5)接口支持多继承, 类只支持单继承
  6)应用场景不同
  如果仅仅是为了扩展类的功能, 优先选择接口
  如果还要体现类与类之间的关系,选择抽象类; 如果除了功能外,还需要保存各种数据,只能选择抽象类; 抽象类的抽象方法需要被子类重写,约束所有的子类都具有某个功能.

4 接口的应用

//定义Usb接口, 有连接设备, 断开连接两个操作
public interface Usb {
	void connect();		//连接
	void  disconnect();		//断开连接
}
// 定义键盘Keyboard类, 实现了Usb接口
class Keyboard implements Usb {

	@Override
	public void connect() {
		System.out.println("键盘已连接, 可以打字了");
	}

	@Override
	public void disconnect() {
		System.out.println("键盘已拔出");
	}

}
//定义鼠标Mouse类,实现了Usb接口
class Mouse implements Usb {

	@Override
	public void connect() {
		System.out.println("鼠标已连接,可以使用了");
	}

	@Override
	public void disconnect() {
		System.out.println("鼠标已拔出");
	}

}

/**
 * * 4) 定义计算机类Computer类,  计算机有一个Usb插槽
 * 		可以把Usb设备插入到Usb插槽中
 * 		可以把Usb插槽上的设备拔下来
 */
public class Computer {
	//Usb插槽可以连接各种Usb设备
	Usb  usbSlot; 			//模拟USB插槽
	
	//模拟把USB设备插入到USB插槽中
	public void insert( Usb  usb) {
		usbSlot = usb ; 		//模拟把USB设备插入到USB插槽
		usb.connect(); 			
	}
	//模拟把USB设备从插槽中拔出
	public void checkout() {
		if ( usbSlot == null ) {
			return ; 			//表示USB插槽上没有设备
		}
		usbSlot.disconnect(); 		//usb插槽上的设备断开连接
		usbSlot = null; 			//usb插槽上没有设备了
	}
}
/**
 * 编写测试类, 测试往电脑上插入键盘, 拔出键盘后再插入鼠标
 *
 */
public class Test {

	public static void main(String[] args) {
		Computer lenovo = new Computer();
		
		Mouse mouse = new Mouse();
		lenovo.insert(mouse);
		lenovo.checkout();		
		
		lenovo.insert( new Keyboard() );
		lenovo.checkout();
		
		lenovo.insert(new Usb() {
			@Override
			public void disconnect() {
				System.out.println("USB打印机断开连接");
			}
			
			@Override
			public void connect() {
				System.out.println("USB打印机连接到电脑");
			}
		});
		lenovo.checkout();
		lenovo.checkout();		
	}
}
鼠标已连接,可以使用了
鼠标已拔出
键盘已连接, 可以打字了
键盘已拔出
USB打印机连接到电脑
USB打印机断开连接

Process finished with exit code 0

5 提倡面向接口的编程

  提倡面向接口的编程
  1)接口使用比较灵活, 一个类在继承父类的同时, 可以实现若干接口 计算机实现了很多的接口
  2)接口比较容易扩展, 接口的引用可以赋值各种实现类对象, 经常把接口的引用作为方法的形参, 在调用方法时,可以传递各种实现类对象 可以在计算机USB插槽上插入/拔出各种USB设备
  3)接口可以使项目分层
  就像有厂商负责生产计算机,有的厂商负责生产键盘, 有的厂商负责生产鼠标一样
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值