이숭간 공부기록
[Java] 인터페이스 (Default Method, 함수형인터페이스, 람다 표현식) 본문
728x90
인터페이스란?
- 기본설계도
- 추상메서드와 상수만 가지며, 데이터를 저장하지않는 개발코드와 객체의 통신접점을 의미한다.
- interface키워드로 선언되며 인터페이스는 다중상속이 가능하다
인터페이스의 구현
- 인터페이스의 모든 추상메소드를 구현한 구현클래스를 작성한다.
- implements키워드를 사용해서 구현한다.
- 만약 구현하는 인터페이스가 어떤 상위 인터페이스를 상속하고 있는경우 구현클래스는 상위인터페이스의 모든 추상메소드까지 전부 구현해야한다.
//추상체
public interface Login {
void login();
}
//구현체
public class KakaoLogin implements Login{
@Override
public void login(){
System.out.println("카카오로 로그인 합니다.")
}
}
public class NaverLogin implements Login{
@Override
public void login(){
System.out.println("네이버로 로그인 합니다.")
}
}
public class UserService implements Login{
private Login login;
public UserService(Login login){
this.login = login;
}
@Override
public void login(){
login.login();
}
}
public class Main() {
public static void main(String[] args){
UserService s = new UserService(new KaKaoLogin());
s.login();
}
}
인터페이스의 목적
- 상속받을 서브클래스에게 구현할 메서드의 원형을 알려주고, 이를 구현하도록 하여 클래스의 동작방식을 일치시킨다.
- 구현객체의 같은 동작을 보장하기위한 목적
- 예를들어, 서로 관련없는 클래스에서 공통적으로 사용하는 방식이 필요하지만, 기능은 각각 구현해야할 필요가 있는경우 사용한다.
- EX) Spring Data JPA에서 지원하는 crudRepository interface가 있습니다. 데이터베이스 사용시 crud의 동작방식은 같지만, 어떤 데이터베이스를 사용하는지에 따라 그 구현에는 차이가 있으므로 이럴때 인터페이스를 사용할 수 있다.
인터페이스의 장점
- 메서드를 호출하는 쪽에서 메서드 내용에 관계없이 선언부만 알면 되기때문에 독립적인 프로그래밍이 가능하다.
- 인터페이스는 선언부만 선언해두기 떄문에 틀만 만들어놓고 일관되고 정해진 규칙에 따른 프로그램개발이 가능하다.
- 부모자식 관계가 아니더라도 인터페이스를 사용하면 각 클래스 사이에 관계를 맺어줄수 있다.
추상클래스와 인터페이스의 공통점
- 인스턴스를 생성할 수 없다.
- 자식클래스 또는 구현클래스가 추상 메서드의 구체적인 동작을 구현하도록 책임을 위임한다.
추상클래스와 인터페이스의 차이점
- 애초에 목적이 다르다.
- 추상클래스는 추상메서드를 자식이 구체화하여 그 기능을 확장하는데 목적이 있다.(is kind of) (ex) 가전제품 - TV, 냉장고)
- 인터페이스는 구현 객체의 같은 동작을 보장하는데 목적이 있다.(can do this) ( ex) 날수 있다 - 비행기, 새)
- 추상클래스는 클래스이지만 인터페이스는 클래스가 아니다.
- 추상클래스는 단일상속이지만 인터페이스는 다중상속이 가능하다. ( 추상클래스는 일반메소드도 포함하기 때문)
Default Method
- 자바8부터 기능이 강화됨
- 인터페이스가 구현체를 가질수 있게됨
- 따라서 디폴트 메소드를 사용하면 기본적인 기능을 탑재한 인터페이스를 만들 수 있다.
- 디폴트 메소드를 갖는 인터페이스를 어떤 클래스가 구현하면, 그 클래스에서 인터페이스의 디폴트메소드를 오버라이드 하지 않아도 기능을 사용할수 있음
- Adapter역할을 하게됨
- 인터페이스에 추상메서드가 10개있다고 해보자
- 어떤 A 클래스에서 그중 1개의 메서드만 필요해서 인터페이스를 구현할경우, 필요없는 나머지 9개의 메서드도 무조건 오버라이드 해줘야하는 상황이 발생한다. 내용없이..
- 그래서 Adapter라는것을 두어 이 Adapter클래스에서 우선적으로 Interface의 10개 메서드를 모두 오버라이딩한다.
- 그후 A클래스에서는 인터페이스를 implements하는것이 아니라 Adapter클래스를 상속받으면된다.
- 그러나 이미 A클래스가 상속받고있는 클래스가 있다면?? 자바에서는 다중상속이 안되기 때문에 울며겨자먹기로 Interface를 구현할수밖에 없다.
- 이럴때 default메서드를 쓰면 되는것이다!! 나머지 9개를 오버라이드 하지 않아도됨
- 인터페이스 추가만으로 (구현없이!) 기능을 확장할 수 있게 됨
- staic메서드도 갖게됨 → 객체생성없이 인터페이스의 static메서드 호출가능, 즉 기능자체만을 담는 기능도 수행하게됨 ( 함수제공자 )
Functional Interface (함수형 인터페이스)
- 자바8에서부터 추가됨
- 추상메소드가 오직 하나만 존재하는 인터페이스
- default나 static메서드가 있어도 상관없다.
- @FuntinalInterface를 달아준다.
인터페이스 임시생성하기
- 익명클래스를 사용해서 인터페이스의 인스턴스를 생성하고 구현을 바로 정의한다.
public class Main {
public static void main(String[] args){
new MySupply(){ // 인터페이스를 바로 new하는 형식으로 익명클래스 생성하여 supply함수 호출
@Override
public String supply() {
return "Hello World";
}
}.supply();
new class XXX implements MySupply {
@Override
public String supply() {
return "Hello World';
}
}.supply();
}
}
- 어떤 인터페이스를 구현하여 메소드를 오버라이드한 클래스의 객체를 만들어서 그 메소드를 호출 → 이름없는 클래스 ( 익명클래스)로 만듬
- Runnable의 run메서드는 MySupply의 supply메소드를 이용하는 메서드
MyRunnable r= new MyRunnable(){
@Override
public void run() {
MySupply s= new MySupply(){
@Override
public String supply(){
return "Hello World";
}
};
System.out.println(s.supply());
}
};
r.run();
익명으로 클래스를 만들수있다면 메서드도 익명으로 사용할 수 없을까?
람다 표현식
- 익명메소드를 사용해 간결한 인터페이스
- Functionalinterface (추상메서드를 1개만 갖는 인터페이스) 에 한해서만 가능
- 어차피 오버라이드할 메서드가 뻔하게 하나밖에 없잖아!
- 간결한 표현이 가능
public class Main2{
public static void main(String[] args){
// 이랬던 코드가
new MyRunnable() {
@Override
public void run() {
System.out.println("Hello");
}
}.run();
// 이렇게 한줄로 변신
MyRunnable r = () -> System.out.println("Hello");
// 예시 -> 바로 윗 블록 13줄 코드와 같음
MyRunnable r3 = () -> {
MySupply s2 = () -> "Hello Hello";
System.out.println(s2.supply());
};
r3.run();
}
}
메소드 레퍼런스
- 람다표현식에서 입력되는 값을 변경없이 바로 사용하는 경우
- 최종으로 적용될 메소드의 레퍼런스를 지정해 주는 표현방식
- 장점 : 입력된 값의 변경이없음을 보장할 수 있다 (
- 들어온값 변경없이 그대로 사용해!!!! 즉 입력값을 변경하지 말라는 표현방식이기도 하다.
- 아 이렇게 해놓은이유는 입력값을 변경하지 말라는거구나, 내가 함부로 바꾸면 안되겟다!
- 개발자의 개입을 차단함으로써 안정성을 얻을 수 있다.
'공부공부 > Java' 카테고리의 다른 글
[Java] 프록시패턴 (Proxy Pattern) (0) | 2021.08.07 |
---|---|
[Java] Object클래스의 메소드 (0) | 2021.08.07 |
[Java] String, StringBuilder, StringBuffer에 대해 알아보자 (0) | 2021.08.02 |
[Java] 자바는 Call by Value일까 Call by Reference일까? (0) | 2021.08.02 |
[Java] 추상클래스와 인터페이스의 차이 (0) | 2021.07.15 |