接口是一个标准
接口是一组方法定义的集合,但是所有方法都没有实现
接口可看做只包含抽象方法的抽象类。
接口天生被用来继承,不能被实例化
语法:public interface 接口名{
返回值类型方法名(参数列表)
}
一个类如果实现某个接口,就必须实现该接口中定义的所有抽象方法
java规定,子类重写父类的方法,访问控制范围必须大于等于父类的方法
实例:只要标含银联标志的ATM取款机,都可以使用5大银行的银行卡,执行基本操作(以建行、农行为例);然后农行实现手机充值和透支的功能;银联内的银行同时受到监控;然后就是动态实例化和动态调用方法
/*
* 封装银联标准功能定义的接口
*/
public interface IUnionPay {
/*
* 定义常量备选项w
* 完整版 public static final String ABC = "ABC";
* public static final会自动添加
*/
String ABC = "ABC";//必须声明时初始化
String CBC = "CBC";
//密码是否验证成功
public abstract boolean checkPwd(String input);
//是否取款成功(public abstract可以省略)
boolean drawMoney(double money);
//返回余额
double getBalance();
//插卡方法的标准定义
void setCard(Card card);
}
public class ATMABC extends ATMCBC implements IABC{
public boolean drawMoney(double money){
//如果余额-取款金额>=-2000,说明在透支范围内,允许透支,并返回true
if ((card.bal-money)>=-2000) {
card.bal-=money;
return true;
}
return false; }
//继承,才能使用其他类的方法,继承ATMCBC使用ATMCBC的三个方法;重写手机充值的方法
public boolean payTelBill(String tel,double money){
如果号码长度是11位,可以充值
// 调用当前的取款方法,取出指定话费
// 如果取款成功,返回true
if(tel.length()==11){
if(drawMoney(money)) {
System.out.println("为"+tel+"号码充值"+money);
return true;
}else{
return false;
}
}else{
return false;
}}}
/*
* 封装农业银行标准功能的接口
*/
public interface IABC extends IUnionPay{
//继承了银联的标准接口,自动继承了银联标准接口的所有抽象方法
//子接口中,仅仅需要定义扩展功能即可
boolean payTelBill(String tel,double money);
}
import java.util.Scanner;
public class InferfaceTest {
public static void main(String[] args) {
// ATMCBC atm = new ATMCBC();
// ATMCBC atm = new ATMCBC();
Card card = new Card("CBC", "123456", 5000);
// atm.takPic();
// atm.setCard(card);
//第二种方法:使用接口类型变量,引用实现类的对象,实现了动态对象的创建和动态方法的调用
IUnionPay atm;
//动态实例化对象
if(card.bank.equals("CBC")){
atm = new ATMCBC();
}else{
atm = new ATMABC();
}
/*
* 第二种方法改良版
* Card card = new Card(IUnionPay.CBC, "123456", 5000);
if(card.bank.equals(IUnionPay.CBC)){
atm = new ATMCBC();
}else if(card.bank.equals(IUnionPay.ABC)){
atm = new ATMABC();
}else{System.out.println("不支持的卡种");
return;}
*/
//将银行卡插入atm
atm.setCard(card);//在父类型IUnionPay中定义标准setCard方法后,此时不再报错
//atm不能再调用takPic()和setCard方法,因为父类型只能调用子类重写的方法
Scanner sc = new Scanner(System.in);
System.out.println("请输入密码");
String input = sc.next();
//建行atm中三个功能测试:验证、取款、查询余额功能测试
// 调用atm验证密码方法
// 如果验证通过:
// 就提示输入取款金额,并保存到money中
// 调用atm取款方法,判断取款金额:
// 如果取款成功,提示卡内余额
// 否则,提示余额不足,取款失败
// if (atm.checkPwd(input)) {
// System.out.println("请输入密码");
// System.out.println("请输入取款金额");
// double money = sc.nextDouble();
// if (atm.drawMoney(money)) {
// System.out.println("取款成功,余额为:"+atm.getBalance());
// }else{
// System.out.println("余额不足,取款失败");
// }
// }else{
// System.out.println("验证失败,退出");
// }
//农行额外的一个功能:充值手机功能测试
// if (atm.checkPwd(input)) {
// System.out.println("请输入手机号");
// String tel = sc.next();
// System.out.println("请输入充值金额");
// double money = sc.nextDouble();
// if (atm.payTelBill(tel, money)) {
// System.out.println("充值成功");
// } else {
// System.out.println("余额不足,充值失败");
// }
// } else {
// System.out.println("号码格式不对");
// }
/*
* 实现接口中的方法,可以选择继承已有类中已实现的接口中的方法,也可以自己重写,
* 比如农行中重写接口中取钱功能,从而实现自己的透支功能;也可以继承建行从而使用建行普通的取款方法
*/
//农行透支功能测试
if (atm.checkPwd(input)) {
System.out.println("请输入取款金额");
double money = sc.nextDouble();
if (atm.drawMoney(money)) {
System.out.println("取款成功,余额为:"+atm.getBalance());
}else{
System.out.println("余额不足,取款失败");
}
}else{System.out.println("密码验证错误");}
}}
/*
* 封装建设银行atm功能类
* 多余atm机类都必须遵守银联中的标准接口
* 并实现接口中抽象方法
*/
public class ATMCBC implements IUnionPay,IPolice{
//接口的实现类中,除了实现接口方法外,也可以定义自己专有成员和方法
public Card card;
public void setCard(Card card){
this.card = card;
}
//@Override:断言机制,告诉编译器当前方法是重写父类方法,请编译器协助检查方法签名,如果重写的方法签名没在父类中找到,则编译错误
public boolean checkPwd(String input) {
//判断输入的input和card对象中的pwd属性是否相同,相同返回true,用equals
if (input.equals(card.pwd)) {
return true;
}else{
return false;
}
}
public boolean drawMoney(double money) {
//先检查card属性bal是否大于等于取款金额,可以true,否则false
if (card.bal>money) {
card.bal-=money;
return true;
}else{
return false;}
}
public double getBalance() {
// TODO Auto-generated method stub
return card.bal ;
}
public void takPic() {
// TODO Auto-generated method stub
System.out.println("您已经让摄像区域");
}
}
public class Card {
public String bank;//银行
public String pwd;//密码
public double bal;//余额
public Card(String bank, String pwd, double bal) {
super();
this.bank = bank;
this.pwd = pwd;
this.bal = bal;
}
}
/*
* 封装派出所要求功能:每个行的atm都可以拍照
*/
public interface IPolice {
void takPic();
}
动态调用接口方法
接口可以作为一种特殊类型声明一个引用类型的变量IUnionPay atm;编译正确
一个接口类型的变量可以引用实现了该接口的类的对象;
IUnionPay atm = new ATMCBC();
IUnionPay atm = new ATMABC();
为什么使用接口类型引用实现类的变量呢?因为可以动态调度!
通过接口类型变量仅能调用实现该接口类中重写的方法:
接口和抽象类
相同点
1.天生都是被继承的,都不能实例化;2.一个类不论是实现接口还是继承抽象类,都必须实现其中所有抽象方法;
3.接口和抽象类都可以声明父类型的变量,引用子类型对象;
4.父类型对象的引用都可以调用子类型对象中重写的方法;
5.因为3,4两条,所以抽象类和接口,都可以实现动态创建对象和动态方法调度;
切记,父类型对象的引用都不能调用子类型对象中非重写的方法
不同点
1.抽象类不允许多继承,而接口可以多继承;
2.使用场景不同:
-抽象类:主要用于封装子类中共享的成员。只有个别方法自己不能实现,才定义为抽象方法,请子类自力更生;
-接口:主要用于定义在程序中定义标准。接口完全不是实现任何方法。
3.成员的修饰词不同:
-抽象类中的成员,可以使用任意关键字修饰;
-接口中的成员变量都是public stati final ,方法都是public abstract只不过可以省略。