OCP Review 2.1 - Interfaces
Interfaces
- Can declare any number of methods
- Can be a marker interface (empty)
- 
    Can extend another interface 
- The methods of an interface are implicitly abstract and public.
- The vairables of an interface are implicitly public, static, and final.
- Because the methods in an interface are implicitly public, if you try to assign a weaker access to the implemented method in a class, it won’t compile.
interface Marker {
}
interface A extends Marker {   
}
Can’t
- a class can’t extend from an Interface
- can’t create an instance of an interface
- can’t contain instance / static blocks of code
Instance of
Marker m = new Marker() {   // this is an anonymous class implementing Marker
};
System.out.println(m instanceof Marker);
We’re instantiating an Object
What does this print?
interface Marker {
}
interface A extends Marker {   
}
// ...
A a = new A() {
};
System.out.println(a instanceof Marker);
System.out.println(a instanceof A);
true and true
Always public abstract
- we can use any form: the compiler treats them as always public abstract
- in the interface definition we can omit public abstract. In the class implementation: NO
public interface Decompress {
    public abstract void decompress();
    abstract void decompress();
    public void decompress();
    void decompress();
}
Interface default implementations
interface Compress {
    void compress();
}
interface CompressExtension extends Compress {
    @Override
    default void compress() {
        System.out.println("I'm compressing");
    }
}
class ZipCompressor implements CompressExtension {
}
Static members in an interface
interface I1 {
    static void sm() {
        System.out.println("Static method");
    }
    
    default void m1() {
        System.out.println("I1::m1");
    }
}
interface I2 extends I1 {
    default void m1() {
        I1.sm();        // we need to use the Interface I1 as sm is defined there
        System.out.println("I2::m1");
    }
}
class A implements I2, I1 {
    @Override
    public void m1() {
        I1.sm();
    }
}
Default implementations useful?
- to move common code from subclasses to small, focused interfaces instead of a big-ass abstract parent class
- f.i. interface FilePersistable: we can persist compressed files, or music, photos, etc.
- the ability to be saved on file is a trait of many different classes
Problem 1
- two different (unrelated) interfaces provide the same default
class ZipCompressor implements CompressExtension, AnotherCompressExtension {    // Error
}
interface CompressExtension extends Compress {
    @Override
    default void compress() {
        System.out.println("I'm compressing in CompressExtension");
    }
}
interface AnotherCompressExtension extends Compress {
    @Override
    default void compress() {
        System.out.println("I'm compressing in AnotherCompressExtension");
    }
}
Problem 1, simplified
interface I1 {
    default void m1() {
        System.out.println("I1::m1");
    }
}
interface I2 {
    default void m1() {
        System.out.println("I2::m1");
    }
}
class A implements I1, I2 {     // COMPILATION ERROR
    
}
Problem 1, solved
interface I1 {
    default void m1() {
        System.out.println("I1::m1");
    }
}
interface I2 extends I1 {
    default void m1() {
        System.out.println("I2::m1");   // this is used
    }
}
class A implements I1, I2 {
}
Problem 2
- one interface provides a default impl
- another interface extends from it and provides a different default impl
class ZipCompressor implements AnotherCompressExtension {
}
interface CompressExtension extends Compress {
    @Override
    default void compress() {
        System.out.println("I'm compressing in CompressExtension");
    }
}
interface AnotherCompressExtension extends CompressExtension {
    @Override
    default void compress() {
        System.out.println("I'm compressing in AnotherCompressExtension");
    }
}
ZipCompressor zc = new ZipCompressor();
zc.compress();                       // I'm compressing in AnotherCompressExtension
((CompressExtension)zc).compress();  // I'm compressing in AnotherCompressExtension
Uses of interfaces & default impl
- To quickly create mocks
- To let you compile and print warning while running