一、接口语法
1、接口也是一种"引用数据类型",编译之后也是一个class字节码文件
2、接口是完全抽象的(抽象类是半抽象)或者也可以说接口是特殊的抽象类。
3、定义接口的语法:[修饰符列表] interface 接口名{}
4、接口支持多继承,一个接口可以继承多个接口。
5、接口中只包含两部分内容:
1)常量
2)抽象方法
6、接口中所有的元素都是public修饰的。(都是公开的)
7、接口中的抽象方法定义时:public abstract修饰符可以省略。
8、接口中的方法都是抽象方法,接口中的方法不能有方法体
9、类和类之间叫做继承,类和接口之间叫做实现
继承使用关键字:extends
实现使用关键字:implemens
10、当一个非抽象的类,实现接口的时候,必须将接口中所有的抽象方法全部实现。
11、一个类可以实现多个接口
12、extends和implements可以共存,extends在前,implements在后。
13、使用接口,写代码的时候,可以使用多态(父类型引用指向子类型对象)
【测试代码一】
package Test;
public class InterfaceTest01 {
public static void main(String[] args) {
//访问接口中的常量
System.out.println(Mymath.PI);
}
}
//定义接口
interface A{
}
//接口支持继承
interface B extends A{
}
//一个接口可以继承多个接口(支持多继承)
interface C extends A,B{
}
interface Mymath{
//常量
//public static final double PI = 3.1415926;
//public static final可以省略
double PI = 3.1415926;
//接口中随便写一个变量就是常量
int k = 100;
//抽象方法
//public abstract int sum(int a, int b);
//接口中的抽象方法定义时:public abstract修饰符可以省略
int sum(int a,int b);
//错误:接口中的抽象方法不能带有方法体
/*
void soSome(){
}*/
}
【测试代码二】
package Test;
public class InterfaceTest02 {
public static void main(String[] args) {
M_Math mm = new MymathImpl04();
mm.sub(10,30);
}
}
interface M_Math{
public static final double PI = 3.1415926;
int sum(int a,int b);
int sub(int a,int b);
}
abstract class MymathImpl01 implements M_Math{
}
abstract class MymathImpl02 implements M_Math{
public int sum(int a,int b){
return a+b;
}
}
abstract class MymathImpl03 implements M_Math{
public int sum(int a,int b){
return a+b;
}
public int sub(int a,int b){
return a-b;
}
}
//当一个非抽象的类实现接口的话,必须将接口中所有的抽象方法全部实现
class MymathImpl04 implements M_Math{
//错误:正在尝试分配更低的访问权限:以前为pubic
/*
int sum(int a, int b) {
return 0;
}*/
@Override
public int sum(int a, int b) {
return a+b;
}
@Override
public int sub(int a, int b) {
return a-b;
}
}
【测试代码三】
package Test;
/**
* 1、 接口和接口之间支持多继承
* 2、 一个类可以实现多个接口。
* 这种机制弥补了java中的哪个缺陷?
* java中类和类只支持单继承,实际上单继承是为了简单而出现的,现实世界中存在多继承,
* java中的接口弥补了单继承带来的缺陷。
* 【注】
* 接口A和接口B虽然没有继承关系,但是写代码的时候,可以互转,
* 编译器没意见,但是运行时可能出现:ClassCastException
*/
public class InterfaceTest03 {
public static void main(String[] args) {
//使用多态
A a = new D();
B b = new D();
C c = new D();
//编译、运行都没问题
//调用其他接口中的方法,需要转型(接口转型)
B b1 = (B)a;
b1.m2();
D d = (D)a;
d.m2();
//编译没问题,运行有问题
M m = new E();
//接口和接口之间在进行强制类型转换的时候,没有继承关系,也可以强转
//但一定要注意,运行时可能会出现classCastException异常
if(m instanceof K){
K k = (K)m;
}
}
}
interface K{
}
interface M{
}
class E implements M{
}
//接口和接口之间支持多继承
interface X{
}
interface Y{
}
interface Z extends X,Y{
}
//一个类可以实现多个接口
interface A{
void m1();
}
interface B{
void m2();
}
interface C{
void m3();
}
//实现多个接口类似于多继承
class D implements A,B,C{
//实现A接口中的m1方法
@Override
public void m1() {
}
//实现B接口中的m2方法
@Override
public void m2() {
System.out.println("m2...");
}
//实现C接口中的m3方法
@Override
public void m3() {
}
}
【测试代码四】
package Test;
/**
* 继承和实现都存在的话:extends关键字在前,implements关键字在后
*/
public class InterfaceTest04 {
public static void main(String[] args) {
Flyable f1= new Cat();
f1.fly();
Flyable f2 = new Pig();
f2.fly();
}
}
//动物类:父类
class Animal{
}
//可飞翔的接口(是一对翅膀)
//接口通常提取的是行为动作
interface Flyable{
void fly();
}
//动物类子类:猫类
class Cat extends Animal implements Flyable{
@Override
public void fly() {
System.out.println("飞猫起飞,翱翔太空");
}
}
//想飞就插翅膀
class Pig extends Animal implements Flyable{
@Override
public void fly() {
System.out.println("我是一只会飞的🐖");
}
}
二、接口在开发中的作用:【解耦合】
【注意】
接口在开发中的作用,类似于多态在开发中的作用
1、多态作用:面向抽象编程,不要面向具体编程,降低程序的耦合度,提高程序的扩展力。
2、接口作用:
1)接口是完全抽象的,
面向抽象编程以后可以修改为:面向接口编程面向抽象编程以后可以修改为:面向接口编程
2)面向接口编程,可以降低程序的耦合度,提高程序的扩展力,符合OCP开发原则,
接口的使用离不开多态机制(接口+多态才可以达到降低耦合度)
3)接口可以解耦合,那么解开的是谁和谁的耦合?
①任何一个接口都有调用者和实现者
②接口可以将调用者和实现者解耦合
③调用者面向接口调用
④实现者面向接口编写实现
4)以后进行大项目的开发,一般都是将项目分离成一个模块一个模块的,
模块和模块之间采用接口衔接,降低耦合度。
【代码】
package Test;
public interface FootMenu {
void yuxiangrousi();
void xihongshichaojidan();
}
package Test;
public class ChineseCook implements FootMenu{
@Override
public void yuxiangrousi() {
System.out.println("中餐厨师做的鱼香肉丝!");
}
@Override
public void xihongshichaojidan() {
System.out.println("中餐厨师做的西红柿炒鸡蛋!");
}
}
package Test;
public class AmericanCook implements FootMenu{
@Override
public void yuxiangrousi() {
System.out.println("西餐厨师做的鱼香肉丝!");
}
@Override
public void xihongshichaojidan() {
System.out.println("西餐厨师做的西红柿炒鸡蛋!");
}
}
package Test;
public class Customer {
private FootMenu footmenu;
public Customer() {
}
public Customer(FootMenu footmenu) {
this.footmenu = footmenu;
}
public FootMenu getFootmenu() {
return footmenu;
}
public void setFootmenu(FootMenu footmenu) {
this.footmenu = footmenu;
}
public void order(String food_name){
String food_name1 = "yuxiangrousi";
String food_name2 = "xihongshichaojidan";
//FootMenu footMenu = footmenu;
FootMenu footMenu = this.getFootmenu();
if (food_name.equals(food_name1)){
footMenu.yuxiangrousi();
}else{
footMenu.xihongshichaojidan();
}
}
}
package Test;
public class Test {
public static void main(String[] args) {
FootMenu fm1 = new ChineseCook();
FootMenu fm2 = new AmericanCook();
Customer customer1 = new Customer(fm1);
customer1.order("xihongshichaojidan");
Customer customer2 = new Customer(fm2);
customer2.order("yuxiangrousi");
}
}