您可能熟悉Kotlin中的[属性委托],但您是否听说过[接口委托]?这是其他编程语言不具备的特性之一。
标准接口的实现
假设下面有两个接口:PrintInterface1和PrintInterface2。
interface PrintInterface1{
fun fun1()
}
interface PrintInterface2{
fun fun2()
}
你有一个实现这两个接口的类。所以它覆盖了这两个接口的fun1()和fun2()。
class PrintManager : PrintInterface1,PrintInterface2{
override fun fun1() {
println("fun1")
}
override fun fun2() {
println("fun2")
}
}
简单说类图如下:
调用者的使用如下所示。
fun main(){
val printManager = PrintManager()
printManager.fun1()
printManager.fun2()
}
这里没有什么特别的,它是一个相当标准的接口实现
委托接口实现
实现上述标准接口的另一种方法是使用委托接口。让我们看看下面的委托接口实现类图。
类不再实现fun1()和fun2()。它将实现委托给PrintInterface1Impl和PrintInterface2Impl的实例。
代码如下:
interface PrintInterface1{
fun fun1()
}
interface PrintInterface2{
fun fun2()
}
class PrintInterface1Impl:PrintInterface1{
override fun fun1() {
println("fun1")
}
}
class PrintInterface2Impl:PrintInterface2{
override fun fun2() {
println("fun2")
}
}
委托实现:
class PrintManager : PrintInterface1 by PrintInterface1Impl(),PrintInterface2 by PrintInterface2Impl(){
}
可以看到,PrintManager类中的fun1()和fun2()实现已经移到了PrintInterface1Impl和PrintInterface2Impl。这样做的好处是使类变得不那么混乱,不会因为不同类型的接口实现而膨胀。
以这种方式使用委托可以帮助减少代码重复,并更容易在对象之间重用和共享功能。
“请注意:PrintInterface1Imp()和PrintInterface2Imp()是类的实例。
您还可以重写委托接口。PrintInterface1Impl.fun1()被下面的PrintManager.fun1()覆盖。
class PrintManager : PrintInterface1 by PrintInterface1Impl(),PrintInterface2 by PrintInterface2Impl(){
override fun fun1() {
println("override fun1")
}
}
Java中实现类似的机制
Java不像Kotlin那样具有作为语言特性的委托接口的概念。但是,可以使用接口和组合在Java中实现类似的机制。
在Java中,可以通过实现接口并将方法调用委托给另一个对象来实现委托。例如,考虑以下接口:
public interface Printable {
void print();
}
我们可以创建一个实现Printable接口的类,并将其实现委托给另一个对象,如下所示:
public class PrinterImpl implements Printable {
@Override
public void print() {
System.out.println("Printing...");
}
}
public class PrintManager implements Printable {
private Printable printer;
public PrintManager(Printable printer) {
this.printer = printer;
}
@Override
public void print() {
printer.print();
}
}
public static void main(String[] args) {
Printable printer = new PrinterImpl();
Printable printManager = new PrintManager(printer);
printManager.print(); // delegates to the PrinterImpl instance
}
在上面的代码中,PrintManager类实现了Printable接口,并将其实现委托给构造函数中传递的另一个Printable对象。当PrintManager被调用以print()时,它将把调用委托给打印机对象,在本例中是PrinterImpl类。
但PrintManager这也会会因为不同类型的接口实现而膨胀
总结:
这样看委托接口是一个语法糖。我个人还没有用过。我不知道我最终是否会用到它。但看起来它是替代继承的一个不错的选择。