Thinking in Java - Study Notes - (9) Interface

Java Programming Ideas - Chapter 9 - Interfaces

Interfaces and inner classes give us a more structured way of separating the interface from the implementation.

abstract classes and abstract methods

Java provides a mechanism called abstract methods (equivalent to pure virtual functions in C++), which are incomplete; only declarations and no method bodies.

    abstract void f();

A class that contains abstract methods is called an abstract class. If a class contains one or more abstract methods, the class must be qualified as abstract. (Otherwise, the compiler will report an error)

If you inherit from an abstract class and want to create objects of that new class, you must provide method definitions for all abstract methods in the base class. If you don't do this (you can choose not to), then the exported class is also abstract, and the compiler will force us to qualify the class with the abstract keyword.

Creating abstract classes and abstract methods is very useful because they make the abstraction of the class explicit and tell the user and the compiler how you intend to use them. Abstract classes are also useful refactoring tools because they allow us to easily move public methods up the inheritance hierarchy.

interface

The interface keyword produces a completely abstract class that does not provide any concrete implementation at all.

An interface means: "All classes that implement that particular interface look like this". Therefore, any code that uses a particular interface knows which methods of that interface are available, and only needs to know those. Therefore, interfaces are used to establish agreements between classes.

However, an interface is not just an extremely abstract class, because it allows one to implement some kind of multiple-subvariant-like feature by creating a type that can be cast to multiple base classes.

You can choose to explicitly declare methods public in an interface, but even if you don't, they're public . Therefore, when implementing an interface, the methods defined in the interface must be defined as public ; otherwise, they will only get default package access, so that in the process of method inheritance, their access is lowered, which is not allowed by the Java compiler .

fully decoupled

import java.util.Arrays;

class Processor {
    public String name() {
        return getClass().getSimpleName();
    }

    Object process(Object input) {
        return input;
    }
}

class Upcase extends Processor {
    @Override
    String process(Object input) { // Covariant return
        return ((String) input).toUpperCase();
    }
}

class Downcase extends Processor {
    String process(Object input) {
        return ((String) input).toLowerCase();
    }
}

class Splitter extends  Processor {
    String process(Object input) {
        return Arrays.toString(((String) input).split(" "));
    }
}
public class Apply {
    public static void process(Processor p, Object s) {
        System.out.printf("Using Processor %s\n", p.name());
        System.out.println(p.process(s));
    }

    public static String s = "Disagreement with beliefs is by definition incorrect";
    public static void main(String[] args) {
        process(new Upcase(), s);
        process(new Downcase(), s);
        process(new Splitter(), s);
    }
} /* 输出结果
Using Processor Upcase
DISAGREEMENT WITH BELIEFS IS BY DEFINITION INCORRECT
Using Processor Downcase
disagreement with beliefs is by definition incorrect
Using Processor Splitter
[Disagreement, with, beliefs, is, by, definition, incorrect]
*/

Multiple Inheritance in Java

Core reason to use an interface: To be able to upcast to multiple base types (and thus flexibility)
Second reason: To prevent client programmers from creating objects of that class, and to ensure that this is just creating an interface.

Extending an interface through inheritance

Try to avoid functions with the same name.

Adapter interface

adapter mode

/*
 * 适配器模式
 */
class FilterAdaptor implements Processor {
    Filter filter;

    public FilterAdaptor(Filter filter) {
        this.filter = filter;
    }

    @Override
    public String name() {
        return filter.name();
    }

    @Override
    public Object process(Object input) {
        return filter.process((Waveform) input);
    }
}

public class FilterProcessor {
    public static void main(String[] args) {
        Waveform w = new Waveform();
        Apply.process(new FilterAdaptor(new LowPass(1.0)), new Waveform());
        Apply.process(new FilterAdaptor(new HighPass(2.0)), w);
        Apply.process(new FilterAdaptor(new BandPass(3.0, 4.0)), w);
    }
}

/*
 * 过滤器基类
 */
class Filter {
    public String name() {
        return getClass().getSimpleName();
    }

    public Waveform process(Waveform input) {
        return input;
    }
}

/*
 * 过滤器导出类
 */
class LowPass extends Filter {
    double cutoff;

    public LowPass(double cutoff) {
        this.cutoff = cutoff;
    }

    @Override
    public Waveform process(Waveform input) {
        return input;
    }
}

class HighPass extends Filter {
    double cutoff;

    public HighPass(double cutoff) {
        this.cutoff = cutoff;
    }

    public Waveform process(Waveform input) {
        return input;
    }
}

class BandPass extends Filter {
    double lowCutoff, highCutoff;

    public BandPass(double lowCut, double highCut) {
        lowCutoff = lowCut;
        highCutoff = highCut;
    }

    public Waveform process(Waveform input) {
        return input;
    }
}

/*
 * 处理对象
 */
class Waveform {
    private static long counter;
    private final long id = counter++;

    public String toString() {
        return "Waveform " + id;
    }
}

domain in interface

Any fields put into an interface are automatically static and final .

These fields are not part of the interface, their values ​​are stored in the static storage area of ​​the interface.

nested interface

Interfaces can be nested within classes or other interfaces.

interface and factory

Interfaces are a way to achieve multiple inheritance, and the typical way to generate objects that conform to an interface is the factory method design pattern.

package thinkinginjava;

public class Factories {
    public static void serviceConsumer(ServiceFactory fact) {
        Service s = fact.getService();
        s.method1();
        s.method2();
    }
    public static void main(String[] args) {
        serviceConsumer(new Implementation1Factory());
        serviceConsumer(new Implementation2Factory());
    }
}

interface Service {
    void method1();

    void method2();
}

interface ServiceFactory {
    Service getService();
}

class Implementation1 implements Service {

    @Override
    public void method1() {
        System.out.println(getClass().getSimpleName() + ": method1");
    }

    @Override
    public void method2() {
        System.out.println(getClass().getSimpleName() + ": method2");
    }
}

class Implementation1Factory implements ServiceFactory {

    @Override
    public Service getService() {
        return new Implementation1();
    }
}

class Implementation2 implements Service {

    @Override
    public void method1() {
        System.out.println(getClass().getSimpleName() + ": method1");
    }

    @Override
    public void method2() {
        System.out.println(getClass().getSimpleName() + ": method2");
    }
}
class Implementation2Factory implements ServiceFactory {

    @Override
    public Service getService() {
        return new Implementation2();
    }
} /* 输出结果
Implementation1: method1
Implementation1: method2
Implementation2: method1
Implementation2: method2
*/

Summarize

Any abstraction should arise from a real need. Interfaces should be refactored when necessary rather than adding an extra level of indirection everywhere, and thus additional complexity.

The proper principle should be to prefer classes over interfaces. Start with classes, and if the necessity of an interface becomes clear, then refactor. Interfaces are an important tool, but they are prone to abuse.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325202914&siteId=291194637
Recommended