为了满足多态的功能,做一些不用来实现的方法父类,我们可以 采用抽象。故引出今天的下文:
不能直接实例化的类,提供其他类的框架和基础功能。包含抽象方法和抽象属性,子类实现抽象方法,扩展功能。
abstract class A {
public abstract void fun();
}
总结抽象类特性
1. 被abstract修饰
2. 无法用new实例化,存在就是为了被继承
3. 必须抽象类才能使用抽象修饰方法
4. 抽象类可以有普通的成员方法与成员变量
5. 普通类继承抽象类后,必须重写这个抽象类中的所有抽象方法
6. 抽象类及抽象方法不可被 final, private, static 修饰
以抽象这个思想引入,就是为了讲接口:
接口,顾名思义,类似电脑的usb接口,电源插座等
只要符合这个插口标准及形态的如电脑的鼠标,键盘都可以接入电脑USB插口,电饭煲,吹风机等家电都可以插入插座的电源接口。
简而言之,接口就像一个公共规范标准,只要符合,大家都可以使用。
在JAVA中,接口可以看成是:多个类的公共规范,是一种引用数据类型。
定义一组方法,提供多态功能。无实例变量,所有方法默认为abstract修饰的。
所有成员变量都是public static final修饰的
由于默认都是抽象方法,故为了简洁性,都建议定义方法直接如下:
public interface Main {
void 接口名称();
}
接口不能直接使用,需要一个“实现类”来实现接口中的所有抽象方法。
类似继承的父与子关系用“extends”连接,接口中实现类和接口之间需要用“implements”连接。
举个例子,直接实战一道题吧。
请实现笔记本电脑使用USB鼠标、USB键盘的例子 1. USB接口:包含打开设备、关闭设备功能 2. 笔记本类:包含开机功能、关机功能、使用USB设备功能 3. 鼠标类:实现USB接口,并具备点击功能 4. 键盘类:实现USB接口,并具备输入功能
//先搞一个USB接口
public interface USB {
void OpenDevice();
void CloseDevice();
}
//鼠标类
public class Mouse implements USB{
public void OpenDevice(){
System.out.println("打开鼠标");
}
public void input(){
System.out.println("点击鼠标");
}
public void CloseDevice(){
System.out.println("关闭鼠标");
}
}
//键盘类
public class Keyboard implements USB{
@Override
public void OpenDevice() {
System.out.println("打开键盘");
}
public void input(){
System.out.println("键盘输入");
}
@Override
public void CloseDevice() {
System.out.println("关闭键盘");
}
}
//电脑类:使用USB设备
public class Computer {
public void Open(){
System.out.println("打开电脑");
}
public void usbDevice(USB usb){
usb.OpenDevice();
if(usb instanceof Mouse){
Mouse mouse = (Mouse) usb;
mouse.input();
} else if (usb instanceof Keyboard) {
Keyboard keyboard = (Keyboard) usb;
keyboard.input();
}
usb.CloseDevice();
}
public void Close(){
System.out.println("关闭电脑");
}
}
//测试类
public class TestUSB {
public static void main(String[] args) {
Computer computer = new Computer();
computer.Open();
//使用鼠标
computer.usbDevice(new Mouse());
//使用键盘
computer.usbDevice(new Keyboard());
computer.Close();
}
}
我们已知,类和类在JAVA只能单继承,一个类自己却可以多接口。。。那,不妨大胆设想一下,类可不可以用接口来达到多继承的目的呢?
聪明的想法!
接口是可以多继承的
如又可以游泳又可以跑步的,我们叫他两栖
那两栖可不可以同时继承跑和游泳两个接口呢
接口间的继承相当于把多个接口合并在一起,如下例子
//跑的接口
interface Running {
void run();
}
//游泳的接口
interface Swimming {
void swim();
}
// 两栖的动物, 既能跑, 也能游
interface Amphibious extends Running, Swimming {
}
//然后用青蛙来对两栖直接接口
class Frog implements Amphibious {
...
}
(抽象类)定义了你是什么,(接口)规定了你能做什么
举个例子
抽象类——我定义了动物是有名字和类别,就像一个图鉴,是纸上的东西,
接口类——这个动物具体能做什么功能,比如青蛙会游泳,鸟不会游泳但会飞
(一个接口最好只能做一件事,你不能要求青蛙能游泳的同时还能飞吧)
专业一点,网上看到了个表格:
我们用父类animal ,接口 飞Flying,跑Running,游泳Swimming,和子类(及实现类)鸟,青蛙来分别呈现一下多态和接口的使用
首先是父类animal
//先整一个父类
public abstract class animal {
//包含名字和年龄
protected String name;
protected int age;
//带参数的构造方法
public animal(String name,int age){
this.name = name;
this.age = age;
}
//这个eat留作后续让子类重写来向上转型的方法
//用来复习多态
public abstract void eat();
}
然后是三个接口
public interface flying {
void fly();
}
public interface Running {
void run() ;
}
public interface Swimming {
void swim();
}
然后是鸟和青蛙
青蛙👇
public class Frog extends animal implements Swimming,Running {
//继承的子类要沿用父类的构造方法
public Frog(String name,int age){
super("青蛙",1);
}
//重写父类eat方法
@Override
public void eat() {
System.out.println(name + "正在吃");
}
//接口的两个方法
//青蛙会跑
@Override
public void run() {
System.out.println("青蛙在跑!");
}
//青蛙会游泳
@Override
public void swim() {
System.out.println("青蛙在游泳!");
}
}
鸟👇
public class Bird extends animal implements flying,Running{
//父类构造方法
public Bird(String name,int age){
super("小鸟",1);
}
//同上,重写父类eat方法
@Override
public void eat() {
System.out.println(name+"在吃!!!");
}
//鸟会飞
public void fly(){
System.out.println("鸟在飞!");
}
//鸟爪也能跑
@Override
public void run() {
System.out.println("鸟在跑!");
}
}
最后是测试类
public class Main {
public static void test(animal animal){
animal.eat();
}
public static void test1(Running run){
run.run();
}
public static void test2(Swimming swim){
swim.swim();
}
public static void test3(flying fly){
fly.fly();
}
public static void main(String[] args) {
Bird bird = new Bird("小鸟",12);
Frog frog = new Frog("青蛙",1);
//eat是父类的函数,此处是多态的实现
test(bird);
test(frog);
//鸟不会游泳,所以无法调用鸟来执行test2
// test2(bird);
test2(frog);
//同理,青蛙不会飞
test3(bird);
// test3(frog);
}
}