-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInterfaceExample.java
More file actions
162 lines (141 loc) · 5.37 KB
/
Copy pathInterfaceExample.java
File metadata and controls
162 lines (141 loc) · 5.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package Phase3_ObjectOrientation.Abstraction;
/**
* Abstraction - Part 2: INTERFACES
* --------------------------------
* An INTERFACE is a CONTRACT - a list of methods a class promises to provide.
* Interfaces are pure abstraction: they describe WHAT a type can do without
* forcing HOW it does it.
* <p>
*
* interface Comparable<T> {
* int compareTo(T other);
* }
* class Customer implements Comparable<Customer> {
* public int compareTo(Customer other) { ... }
* }
* <p>
*
* Modern Interface Members (Java 8 / 9)
* -------------------------------------
* - ABSTRACT methods - implicit public, no body. The original purpose.
* - default methods (Java 8) - have a body; implementors inherit them.
* - static methods (Java 8) - utility tied to the interface itself.
* - private methods (Java 9) - helper for default/static methods.
* - public static final constants (no other fields are allowed).
* <p>
*
* (For a deeper dive into default/static/private interface methods see
* Basics/Methods/InterfaceMethods.java.)
* <p>
*
* Key Properties
* --------------
* - A class can IMPLEMENT MULTIPLE interfaces (Java's answer to multiple
* inheritance of TYPE - not of state).
* - All members are implicitly PUBLIC unless declared private.
* - All fields are implicitly PUBLIC STATIC FINAL.
* - Interfaces cannot have INSTANCE fields and cannot define a constructor.
* - An interface variable can hold any concrete implementor:
* <p>
*
* List<String> xs = new ArrayList<>(); // List is an interface
* <p>
*
* Functional Interfaces
* ---------------------
* An interface with exactly ONE abstract method (SAM - Single Abstract
* Method). It can be the target of a lambda expression or method reference.
* Annotate with @FunctionalInterface so the compiler enforces the SAM rule.
* <p>
*
* @FunctionalInterface
* interface Calculator {
* int apply(int a, int b);
* }
* Calculator add = (a, b) -> a + b;
* add.apply(2, 3); // -> 5
* <p>
*
* The Example Below
* -----------------
* - Drawable - interface with an abstract method + a default + a static helper
* - Resizable - separate interface (demonstrates MULTIPLE implementation)
* - Calculator - functional interface used with a lambda
* - Circle implements Drawable, Resizable
* - Rectangle implements Drawable (only)
*/
public class InterfaceExample {
/** A behavioural contract. */
interface Drawable {
// Abstract - all implementors must provide it
void draw();
// default - inherited unless overridden
default void drawTwice() {
draw();
draw();
}
// static - tied to the interface, callable as Drawable.brush(...)
static String brush() { return "default-brush"; }
}
/** Another contract - a class can implement BOTH. */
interface Resizable {
void resize(double factor);
}
/** Functional interface - exactly one abstract method. */
@FunctionalInterface
interface Calculator {
int apply(int a, int b);
}
// ============================================================
// Implementations
// ============================================================
static class Circle implements Drawable, Resizable {
private double radius;
Circle(double radius) { this.radius = radius; }
@Override
public void draw() {
System.out.println("Drawing a circle of radius " + radius);
}
@Override
public void resize(double factor) {
this.radius *= factor;
System.out.println("Circle resized to radius " + radius);
}
}
static class Rectangle implements Drawable {
double w, h;
Rectangle(double w, double h) { this.w = w; this.h = h; }
@Override
public void draw() {
System.out.println("Drawing a " + w + "x" + h + " rectangle");
}
}
public static void main(String[] args) {
section("Polymorphism through an interface");
Drawable[] items = { new Circle(2), new Rectangle(3, 4), new Circle(5) };
for (Drawable d : items) {
d.draw();
}
section("Default method inherited from the interface");
items[0].drawTwice(); // uses the inherited default
section("Static method on the interface");
System.out.println("Drawable.brush() = " + Drawable.brush());
section("Multiple interface implementation");
Circle c = new Circle(1);
c.draw(); // Drawable behaviour
c.resize(2.5); // Resizable behaviour
// instanceof works for any interface the object implements
System.out.println("c instanceof Drawable = " + (c instanceof Drawable));
System.out.println("c instanceof Resizable = " + (c instanceof Resizable));
section("Functional interface + lambda");
Calculator add = (a, b) -> a + b;
Calculator mul = (a, b) -> a * b;
System.out.println("add.apply(3, 4) = " + add.apply(3, 4)); // 7
System.out.println("mul.apply(3, 4) = " + mul.apply(3, 4)); // 12
// OUTPUT
// (matches the inline comments above)
}
private static void section(String title) {
System.out.println("\n====== " + title + " ======");
}
}