inteface 인터페이스이름 {
public static final 타입 상수이름 = 값;
public abstract 메서드이름(매개변수목록);
}
interface
interface 인터페이스이름 {
public static final int one = 1;
final int two = 2; // public static final int two = 2;
static int three = 3; // public static final int three = 3;
int four = 4; // public static final int four = 4;
public abstract String getSomething();
String getOther(); // public abstract String getOther();
}
implements
를 사용하여 인터페이스에 정의된 추상메서드를 완성하면 인스턴스를 생성할 수 있다. public interface Car {
void run();
void stop();
}
public class BungBung implements Car{
@Override
public void run() {
System.out.println("brrrrr");
}
@Override
public void stop() {
System.out.println("Kkik!");
}
}
implements
뒤에는 여러 인터페이스가 올 수 있다. class A implements B, C
class A extends B implements C
Car car = new BungBung(); // class BungBung implements Car
public class BungBung implements Car{
@Override
public void run() {
System.out.println("brrrrr");
}
@Override
public void stop() {
System.out.println("Kkik!");
}
public void greet(Car car) {
System.out.println("hello");
}
}
public class InterfacePractice {
public static void main(String[] args) {
Car car = new BungBung();
BungBung bung = new BungBung();
bung.greet(car);
}
}
public class BungBung implements Car{
@Override
public void run() {
System.out.println("brrrrr");
}
@Override
public void stop() {
System.out.println("Kkik!");
}
public Car copy() {
return new BungBung();
}
}
public interface GroupedInterface extends Interface1, Interface2, Interface3 {
}
public interface DoItPlus extends DoIt {
boolean didItWork(int i, double x, String s);
}
public interface DoIt {
void doSomething(int i, double x);
int doSomethingElse(String s);
default boolean didItWork(int i, double x, String s) {
// Method body
}
}
public interface Car {
void run();
void stop();
default void refuel() {
System.out.println("yummy");
}
}
public class BungBung implements Car{
@Override
public void run() {
System.out.println("brrrrr");
}
@Override
public void stop() {
System.out.println("Kkik!");
}
@Override
public void refuel() {
System.out.println("yummy yummy!");
}
}
public interface NewCar extends Car{
@Override
void refuel();
}
public class OverridingPriority {
public static void main(String... args) {
Pegasus myApp = new Pegasus();
System.out.println(myApp.identifyMyself()); // "I am a horse."
}
}
class Horse {
public String identifyMyself() {
return "I am a horse.";
}
}
interface Flyer {
default public String identifyMyself() {
return "I am able to fly.";
}
}
interface Mythical {
default public String identifyMyself() {
return "I am a mythical creature.";
}
}
class Pegasus extends Horse implements Flyer, Mythical {
}
한 예를 들면, 한 클래스가 여러 인터페이스를 implements 했고, 그 인터페이스 목록들에 같은 메소드가 있을 때 그 중 누군가가 한 인터페이스를 오버라이딩을 했다면 그것을 따른다. (더 구체화된 메소드를 따른다)
public interface Animal {
default public String identifyMyself() {
return "I am an animal.";
}
}
public interface EggLayer extends Animal {
default public String identifyMyself() {
return "I am able to lay eggs.";
}
}
public interface FireBreather extends Animal { }
public class Dragon implements EggLayer, FireBreather {
public static void main (String... args) {
Dragon myApp = new Dragon();
System.out.println(myApp.identifyMyself()); //I am able to lay eggs.
}
}
지금 여기서 Droagon은 EggLayer와 FireBreather를 implements 했는데 이 두 후보 중에서 EggLayer가 해당 메소드를 오버라이딩 했으므로 FireBreather의 메소드는 무시된다.
아래와 같은 경우를 보면,
interface MyInterfaceA {
default void print() {
System.out.println("Print in MyInterfaceA");
}
}
interface MyInterfaceB extends MyInterfaceA {
default void print() {
System.out.println("Print in MyInterfaceB");
}
}
class MyClass1 implements MyInterfaceA {
}
class MyClass2 extends MyClass1 implements MyInterfaceA, MyInterfaceB {
}
public class OverridingPriority {
public static void main(String... args) {
MyClass1 myClass1 = new MyClass1();
myClass1.print(); // Print in MyInterfaceA
MyClass2 myClass2 = new MyClass2();
myClass2.print(); // Print in MyInterfaceB
}
}
myClass2.print() 할 때 어떤 메소드를 호출할지를 결정해야한다. 규칙1에 따라 클래스가 우선시 되서 MyClass1의 메소드가 가장 우선시 되야 할 것이다. 하지만 MyClass1는 해당 메소드는 구현하고 있지 않아 규칙1이 적용될 수 없다.
규칙2에 따라 더 구체적인 디폴트 메소드가 우선시되므로 (MyInterfaceA 보다 MyInterfaceB가 더 구체적이라 이와 같은 결과가 나왔다.
public interface OperateCar {
// ...
default public int startEngine(EncryptedKey key) {
// Implementation
}
}
public interface FlyCar {
// ...
default public int startEngine(EncryptedKey key) {
// Implementation
}
}
interface MyInterfaceA {
default void print() {
System.out.println("Print in MyInterfaceA");
}
}
class MyClass2 implements MyInterfaceA {
}
위에서는 컴파일에러가 안난다. 디폴트 메서드가 있으니까
interface MyInterfaceA {
default void print() {
System.out.println("Print in MyInterfaceA");
}
}
abstract class MyClass1 {
public abstract void print();
}
class MyClass2 extends MyClass1 implements MyInterfaceA {
} // 컴파일 에러
하지만 위처럼 되면 MyInterfaceA에서 메소드를 구현해 줌에도 불구하고 컴파일 에러가 난다. 추상메소드와 디폴트 클래스가 충돌하기 때문. MyClass2에서 다시 오버라이딩 해줘야 한다.
그런데 MyInterfaceA에 있는 것을 굳이 반복해서 쓸 필요가 없다. super
를 사용하면 된다.
interface MyInterfaceA {
default void print() {
System.out.println("Print in MyInterfaceA");
}
}
abstract class MyClass1 {
public abstract void print();
}
class MyClass2 extends MyClass1 implements MyInterfaceA {
public void print() {
MyInterfaceA.super.print(); // Print in MyInterfaceA
}
}
요약
- 규칙 1. 클래스가 항상 우선
- 규칙 2. 더 구체적인 디폴트를 제공하는 인터페이스가 우선.
public interface Car {
void run();
void stop();
default void refuel() {
System.out.println("yummy");
}
static void introduce() {
System.out.println("Car");
}
}
public class InterfacePractice {
public static void main(String[] args) {
Car.introduce(); //Car
}
}
public interface Temp {
public abstract void mul(int a, int b);
public default void add(int a, int b) {
// private method inside default method
sub(a, b);
// static method inside other non-static method
div(a, b);
System.out.print("Answer by Default method = ");
System.out.println(a + b);
}
public static void mod(int a, int b) {
div(a, b); // static method inside other static method
System.out.print("Answer by Static method = ");
System.out.println(a % b);
}
private void sub(int a, int b) {
System.out.print("Answer by Private method = ");
System.out.println(a - b);
}
private static void div(int a, int b) {
System.out.print("Answer by Private static method = ");
System.out.println(a / b);
}
}