A preface.

Usually, we may be faced with a scenario where there are many methods on an interface of the system, and our business needs to implement the interface. What we really need are only a few methods of the interface, but we have to rewrite other useless methods to implement the interface, resulting in a large pile of useless code, such as:

public interface Way {
   void solve2(a);
   void solve1(a);
   void solve3(a);
   void solve4(a);
}

/** * The only method we really need for this interface is solve2, but the other three interfaces of the interface have to be rewritten * and given an empty implementation, resulting in useless code pile */
Way way = new Way() {
    @Override
    public void solve2(a) {
        System.out.println("child solve2");
    }

    @Override
    public void solve1(a) {}@Override
    public void solve3(a) {}@Override
    public void solve4(a) {}}Copy the code

This article focuses on how to solve this pain point from the perspective of Java and Kotlin respectively

Java optimization interface implementation

  1. Interfaces belong to system API or third-party library API definitions

Using the Way example above, if the interface is system-provided, we can use an abstract class approach as a bridge between the business code implementation and the system interface

Define an abstract class that implements all methods of the Way interface:

public abstract class WayAdapter implements Way {

    @Override
    public void solve2(a) {}@Override
    public void solve1(a) {}@Override
    public void solve3(a) {}@Override
    public void solve4(a) {}}Copy the code

So if the business needs to use the system interface Way, we do not implement Way directly inherit the above class WayAdapter, selectively rewrite the method we need, without additional processing of other unnecessary methods

@Test
public void main(a) {
    Way way = new WayAdapter() {
        @Override
        public void solve2(a) {}}; }Copy the code

Animation The listener class AnimatorListenerAdapter is based on this

  1. Interfaces belong to their own business layer definition

We use the Java8 default keyword directly to change the way the interface part of the method is defined: default in the interface to modify the method can be directly in the interface to give an empty implementation, subclasses do not need this method and do not need additional overwriting

public interface Way {
   void solve2(a);
   
   default void solve1(a) {}default void solve3(a) {}default void solve4(a) {}}Copy the code

If the Way interface forces the solve2 subclass to be overridden and the other methods optional, we simply give the optional method an empty implementation with the default modifier

@Test
public void main(a) {
    Way way = new Way() {
        @Override
        public void solve2(a) {}}; }Copy the code

Lifecycle’s DefaultLifecycleObserve is based on this

Kotlin optimized interface implementation

  1. Interfaces belong to system API or third-party library API definitions

Kotlin has two solutions to this situation:

  • As in Java above, it is solved by an intermediate abstract class
interface Color {
    fun alpha(a)
    fun result(a)
    fun process(a)
}

abstract class ColorAdapter: Color {
    override fun alpha(a){}override fun result(a){}override fun process(a){}}Copy the code
  • Through the syntax features of the Kotlin DSL
// Get an object of interface type Color
fun obtainColor(block: ColorAdapter. () - >Unit): Color {
    return ColorAdapter().apply(block)
}

class ColorAdapter : Color {
    private var alpha: (() -> Unit)? = null
    private var result: (() -> Unit)? = null
    private var process: (() -> Unit)? = null

    fun setAlpha(block: () -> Unit) {
        alpha = block
    }

    fun setResult(block: () -> Unit) {
        result = block
    }

    fun setProcess(block: () -> Unit) {
        process = block
    }

    override fun alpha(a){ alpha? .invoke() }override fun result(a){ result? .invoke() }override fun process(a){ process? .invoke() } }Copy the code

Where the business needs it, it can be used as follows:

Call the required setResult or setResult() or setProcess() method as required by the business
val color: Color = obtainColor {
    setResult {
        // Todo implements specific code logic}}Copy the code
  1. Interfaces belong to their own business layer definition

This approach is basically the same as the Java approach, except that Kotlin does not add default

interface Color {
    fun alpha(a){}fun result(a){}fun process(a)
}

Copy the code

Use:

val color2: Color = object : Color {
    override fun process(a){}}Copy the code

Iv. Easter Eggs (Digression)

If Kotlin needs to define a functional interface (an interface that contains only one method), Kotlin has two options:

  • If you want to implement the SAM transformation, the Kotlin interface definition needs to be preceded by afunThe keyword
fun interface Tree {
    fun num(a)
}
Copy the code
  • Use kotlin-specific function types directly without defining interfaces:

var listen: ((View) -> Unit)? = null