0x01.About
查了一些国内资料,都说java中extended与implements的区别是,一个类只能有一个继承,一个类可以有多个容器。
后来去看了些国外资料。
在我理解上,interface就是一个公共的类,可以包含公共函数、变量。
Java接口是用于指定一组抽象方法的类来实现一个抽象类型。
当一个类实现一个接口,它必须继承所有的内声明的抽象方法,好像签订了一份合同,并履行协议。
0x02.Example
先来看看怎么声明一个接口,文件保存为 InterFace.java
:
public class InterFace {
public static void main(String[] args) {
MyTest x = new MyTest();
x.speak();
x.say();
x.fuck();
}
}
class MyTest implements MyInterface2, MyInterface3 {
@Override
public void speak() {
System.out.println("MyTest Called => jump() =>"+MyInterface.hello);
}
@Override
public void fuck() {
System.out.println("MyTest Called => fuck()");
}
@Override
public void say() {
System.out.println("MyTest Called => say()");
}
}
interface MyInterface1{
public String hello = "hello";
public void speak();
}
interface MyInterface2{
public int num = 1;
public void fuck();
}
// 接口之间可以相互继承
interface MyInterface3 extends MyInterface1{
public void say();
}
输出如下:
$javac InterFace.java
$java InterFace
MyTest Called => jump() =>hello
MyTest Called => say()
MyTest Called => fuck()
这里我们声明了3个接口,并且interface3继承自interface1,所以当类容器导入接口interface3就会导入父类接口interface1。
只要添加了容器implements,就会包含接口中的所有东西,所以必须在MyTest
类中添加该重写函数,否则找不到该函数会报错。
再看下面一个例子,多个类共同使用一个interface接口,保存为Account.java
:
interface Transaction {
int BALANCE = 500;
Object transaction(Object input);
}
class CurrentAccount implements Transaction {
int bal;
public Object transaction(Object input) {
this.bal = BALANCE - (int)input;
return bal;
}
public String toString() { return "Current acc"; }
}
class SavingsAccount implements Transaction {
int bal;
public Object transaction(Object input) {
this.bal = BALANCE + (int)input;
return bal;
}
public String toString() { return "Savings acc"; }
}
public class Account {
public static void payment(Transaction t, Object input) {
System.out.println(t + " is debited: " + t.transaction(input));
}
public static void deposit(Transaction t, Object input) {
System.out.println(t + " is credited: " + t.transaction(input));
}
public static void main(String[] args) {
Integer input = new Integer(600);
deposit(new SavingsAccount(), input);
payment(new CurrentAccount(), input);
}
}
代码输出:
$javac Account.java
$java Account
Savings acc is credited: 1100
Current acc is debited: -100
一个接口可以供多个类共同使用,并且多个类之间使用不冲突,这样看来,interface倒有点像是静态函数了。
观察一下这两个实现类活期账户和储蓄账户自动的向上转型在接受Transaction接口Account类中的方法。
payment()和deposit()方法利用我们所讲的战略设计模式,代表了接口的实现完全脱钩的一个实例。
从理论上说,你可以适应任何类,只需使它们符合的界面,使用这些方法。
对于接口与容器,我见过的一个更具有实用价值的地方,在于类之间的监听函数调用。
类似于js中的事件驱动函数,当有事件发生时候,通过回调函数,通知主函数。
实例代码如下,文件命名为Homeway.java:
public class Homeway {
public static void main(String[] args) {
System.out.println("\n=======================Implements======================\n");
ClassImplements mClassImplements = new ClassImplements();
mClassImplements.run();
}
}
class ClassImplements implements Implements1.Listener {
public Implements1 mImplements1 = null;
public ClassImplements(){
mImplements1 = new Implements1();
mImplements1.setListener(this);
}
@Override
public void onCallStart(){
System.out.println("ClassImplements => onCallStart()");
}
@Override
public void onCallStop(){
System.out.println("ClassImplements => onCallStop()");
}
public void run(){
mImplements1.run();
}
}
//test 2level implements for class
class Implements1 implements Implements2.Listener {
private Listener mListener;
private Implements2 mImplements2;
public Implements1(){
mImplements2 = new Implements2();//把当前类传给下个类
mImplements2.setListener(this);
System.out.println("Init Implements1 =>...");
}
public static interface Listener {
void onCallStart();
void onCallStop();
}
public void setListener(Listener listener) {
mListener = listener;
}
@Override
public void onCallStart(){
System.out.println("Implements1 => onCallStart()");
mListener.onCallStart();//call at Implements1 and then throw to ClassImplements
}
@Override
public void onCallStop(){
System.out.println("Implements1 => onCallStop()");
mListener.onCallStop();//call at Implements1 and then throw to ClassImplements
}
public void run(){
this.mImplements2.run();
}
}
//3 level implement test
class Implements2{
private Listener mListener;
public Implements2(){
System.out.println("Init Implements2 =>...");
}
public static interface Listener {
void onCallStart();
void onCallStop();
}
public void setListener(Listener listener) {
mListener = listener;
}
public void onCallStart(){
System.out.println("Implements2 => onCallStart()");
}
public void onCallStop(){
System.out.println("Implements2 => onCallStop()");
}
public void run() {
System.out.println("Run some functions and then callback from Listener...");
mListener.onCallStart();
mListener.onCallStop();
}
}
输出如下:
$javac Homeway.java
$java Homeway
=======================Implements======================
Init Implements2 =>...
Init Implements1 =>...
Run some functions and then callback from Listener...
Implements1 => onCallStart()
ClassImplements => onCallStart()
Implements1 => onCallStop()
ClassImplements => onCallStop()
我们先是声明了类ClassImplements,这个是我们的主类,并且implements了Implements1.Listener
通过一个Listener建立了监听接口,
然后Implements1
又implements了Implements2.Listener
建立了第2级的监听。
一旦Implements1
或Implements2
内的某个函数触发了某个事件,就能通过监听接口发送给主函数ClassImplements
,类似js中的事件回调函数。
父类与子类通过Listener实现接口调用,此时Listener即为父类本身。
大致的模型如下:
implements容器与interface接口在java类中有很多很好用的模型,有时间该多去研究研究。
参考资料:
- 《Java Interfaces》
- 《Java interfaces and the concept of multiple inheritance》
- 《Java Interface Example, Explanation, and Implementation》