5.实现多个接口
在Java中,类和类之间是单继承的,一个类只能有一个父类,即Java中不支持多继承,但是一个类可以实现多个接口。下面通过类来表示一组动物。
//动物类 public class Animals { protected String name; protected int age; public Animals(String name, int age) { this.name = name; this.age = age; } }
有的动物会飞,有的动物会跑,有的动物会游泳,还有的动物可能有这三种中的多种,可以设为接口。
//接口,分别表示会飞的、会跑的、会游泳的 interface Flying{ void fly(); } interface Running{ void running(); } interface Swimming{ void swimming(); }
下面创建具体的动物。
猫,是一种会跑的动物。
//猫类 public class Cats extends Animals implements Running{ public Cats(String name, int age) { super(name, age); } @Override public void running() { System.out.println(this.name+"用四只腿跑~"); } }
鱼,是一种会游的动物。
public class Fish extends Animals implements Swimming{ public Fish(String name, int age) { super(name, age); } @Override public void swimming() { System.out.println(this.name+"用尾巴游泳"); } }
青蛙,是一种既能跑又能游的两栖动物。
//青蛙类 public class Frog extends Animals implements Running,Swimming{ public Frog(String name, int age) { super(name, age); } @Override public void running() { System.out.println(this.name+"可以用两只脚跳"); } @Override public void swimming() { System.out.println(this.name+"可以用两只脚两只手游"); } }
注意:一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类。(IDEA 中使用 ctrl + i 快速实现接口)
鸭子,是一种海陆空三栖动物,既可以跑又可以游还能飞。
//鸭子类 public class Duck extends Animals implements Flying,Running,Swimming{ public Duck(String name, int age) { super(name, age); } @Override public void fly() { System.out.println(this.name+"可以用两个翅膀飞"); } @Override public void running() { System.out.println(this.name+"可以两只脚跑"); } @Override public void swimming() { System.out.println(this.name+"可以用两只脚和两个翅膀游"); } }
//测试 public class text { public static void main(String[] args) { Cats cat=new Cats("小猫",5); cat.running(); System.out.println("===="); Fish fish=new Fish("小鱼",2); fish.swimming(); System.out.println("===="); Frog frog=new Frog("小青蛙",3); frog.running(); frog.swimming(); System.out.println("===="); Duck duck=new Duck("小鸭子",6); duck.fly(); duck.running(); duck.swimming(); } }
上面的代码展示了 Java 面向对象编程中最常见的用法: 一个类继承一个父类, 同时实现多种接口。继承表达的含义是 is - a 语义, 而接口表达的含义是 具有 xxx 特性。如上述的猫,是一种动物,具有跑的特性;鱼,是一种动物,具有在水中游的特性等等。
6.接口间的继承
在Java中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。即:用接口可以达到多继承的目的。接口可以继承一个接口, 达到复用的效果. 使用 extends 关键字。
例如
//接口,表示跑 interface Running{ void run(); } //接口,表示游 interface Swimming{ void swimming(); } //接口,表示两栖动物(既能跑又能游),这里extends表示拓展 interface Amphibious extends Running,Swimming{ } //青蛙类 class Frog implements Amphibious{ //... }
此时实现接口创建的 Frog 类, 就继续要实现 run 方法, 也需要实现 swim 方法。接口间的继承相当于把多个接口合并在一起。
7.接口使用实例
给对象数组排序
public class Students { private String name; private int age; public Students(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Students{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
定义一个学生数组对象并对数组中的元素进行排序
Students[] students=new Students[3]; students[0]=new Students("zhangsan",15); students[1]=new Students("lisi",10); students[2]=new Students("wangwu",30);
,之前我们学过,数组自带有排序方法,是否可以直接使用这个方法呢?
Arrays.sort(students); System.out.println(Arrays.toString(students));
我们会发现,编译通过,但运行报错。仔细一想,之前数组中每一个元素是整数,可以直接比较大小,而在这里,数组中的元素为一个个的学生,而两个学生的大小关系无法确定,需要我们额外指定比较方式。
让我们的 Students 类实现 Comparable 接口, 并实现其中的 compareTo 方法
public class Students implements Comparable(也可以写成Comparable<T>,T表示要比较的数据类型) { //表示当前的类是可以比较的 private String name; private int age; public Students(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "{"+ "name=" + name + ", age=" + age+ "}"; } //重写字符串比较函数 @Override //Object类型的变量o public int compareTo(Object o) { Students s=(Students)o;//强制类型转换 /*if(this.age>s.age){ return 1; } else if (this.age<s.age) { return -1; }else { return 0; }*/ return this.age-s.age; } }
在 sort 方法中会自动调用 compareTo 方法. compareTo 的参数是 Object , 其实传入的就是 Student 类型的对象 。然后比较当前对象和参数对象的大小关系(按年龄计算):如果当前对象应排在参数对象之前, 返回小于 0 的数字;如果当前对象应排在参数对象之后, 返回大于 0 的数字;如果当前对象和参数对象不分先后, 返回 0;
import java.util.Arrays; public class Text { public static void main(String[] args) { Students[] students=new Students[3]; students[0]=new Students("张三",15); students[1]=new Students("李四",10); students[2]=new Students("王五",30); Arrays.sort(students); System.out.println(Arrays.toString(students)); } }
注意:对于 sort 方法来说, 需要传入的数组的每个对象都是 "可比较" 的, 需要具备 compareTo 这样的能力. 通过重写 compareTo 方法的方式, 就可以定义比较规则。这种对类的入侵性比较强,一旦写好规定的比较方式,那么以后只能以这种方式比较。
第二种方式,构造比较器类
public class Students { public String name; public int age; public Students(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "{" + "name=" + name + ", age=" + age + "}"; } }
//比较器 class ageComparator implements Comparator<Students> { @Override public int compare(Students o1,Students o2) { return o1.age- o2.age; } } class nameComparator implements Comparator<Students>{ @Override public int compare(Students o1, Students o2) { //String 自己重写compareTo 方法 return o1.name.compareTo(o2.name); } } public class Text { public static void main(String[] args) { Students[] students=new Students[3]; students[0]=new Students("zhangsan",15); students[1]=new Students("lisi",10); ageComparator ageComparator1=new ageComparator(); Arrays.sort(students,ageComparator1); System.out.println(Arrays.toString(students)); System.out.println("====="); nameComparator nameComparator1=new nameComparator(); Arrays.sort(students,nameComparator1); System.out.println(Arrays.toString(students)); } }
注意:这种方式做到灵活比较,想用那种方式就调用哪种方式。