구현을 강제
인터페이스는 모든 메서드가 추상 메서드이기에 사용시 구현을 강제한다.
다형성을 제공
호스트 코드(설정 파일들 드에 따라 결정을 하는 부분)에 따라서 메서드 동작이 달라진다.
결합도를 낮추는 효과(의존성을 역전 )
// Login 사용
class UserService implements Login {
private Login login
...
}
interface Login {...}
// Login 구현
class NaverLogin implements Login {...}
class KakaoLogin implements Login {...}
→ 의존성을 주입받았다(DI, Dependency Injection)
→ 의존도를 낮춘다.
→ Dependency Inversion(의존성 역전)이 되었다.
class AClass extends Adapter {
@Override
public void method1() {...} // 필요한 것만 오버라이드 한다.
}
class Adapter implements interface {
@Override
public void method1() {...}
@Override
public void method2() {...}
}
interface AInterface {
void method1(); // AClass에게 필요 O
void method2(); // AClass에게 필요 X
}
Adapter class를 이용하여 필요한 메서드만 구현할 수 있게 되었다. 하지만 Java는 단일 상속만 가능하다. 만약 AClass가 이미 상속을 받고 있다면 Adapter class를 사용할 수 없다.class AClass extends Object implements AInterface {
@Override
public void method1() {...} // 필요한 것만 오버라이드 한다.
}
interface AInterface {
default void method1(){}; // AClass에게 필요 O
default void method2(){}; // AClass에게 필요 X
}
Java의 다중 상속 불가능으로 인해 생긴 위의 문제를 default 메서드를 통하여 해결할 수 있다.@FunctionalInterface
interface MyMap {
void map();
default void sayHello(){...}
default void sayBye(){...}
}
public interface Predicate<T> {
// return true if the input argument matches the predicate, otherwise false
boolean test(T t);
}
public interface Consumer<T> {
// Performs this operation on the given argument.
void accept(T t);
}
public interface Function<T, R> {
// Applies this function to the given argument.
R apply(T t);
}
인터페이스는 스스로 new 할 수 없다.
인터페이스를 사용하기 위해서는 다른 클래스가 필요하다. → 귀찮음 발생😮💨
익명클래스를 사용해서 인터페이스의 인스턴스를 생성하고 구현을 바로 정의한다.
interface MySupply {
String supply();
}
// 익명 클래스 생성
MySuuply s = new MySupply() {
@Override
public String supply() {
return "Hello World";
}
}.supply();
{}
, return
생략MyRunnable r = new MyRunnable() {
@Override
public void run() {
MySupply s = new MySupply() {
@Override
public String supply() { return "Hello Hello"; }
};
System.out.println(s.supply());
}
};
MyRunnable r3 = () -> {
// 익명 함수
MySupply s2 = () -> "Hello Hello";
System.out.println(s2.supply());
};
ClassName::MethodName
@FunctionalInterface
public interface MyMapper<IN, OUT> {
OUT map(IN s);
}
// lamda
MyMapper<String, Integer> m = s1 -> s1.length();
// method reference
MyMapper<String, Integer> m = String::length;
Lamda와 method reference는 IntelliJ의 도움을 받으며 익숙해지자!