Java_인터페이스

song·2023년 10월 18일

Java

목록 보기
24/36

인터페이스(interface)

  • 빡센 추상 클래스
    모든 내용물이 추상이어야 한다.
  • 엄청 중요
    1. 추상클래스는 abstract가 들어가는 애가 있고, 구현부를 작성해서 abstract를 안붙이는 메서드들이 있어도 되는 반면 인터페이스는 모두 abstract를 가져야 한다.
    2. 다중 상속가능
      • 그러나 인터페이스끼리만 상속이 가능하다. (추상클래스도 불가능. )
      • 인터페이스끼리 상속은 extends로 하는데 다중 상속 가능하다.
        interface 이름 extends 인터페이스1, 인터페이스2, 인터페이스3{}
      • 다중 상속이 안되는 이유는 만약 같은 메서드를 가지고 있을 때 어떤 클래스의 메서드를 써야 할 지 모르겠으니 충돌나서 아예 막아놓은 건데, 인터페이스는 구현부가 없고 선언만(이름만) 있기 때문에 가능한 것이다.
      • 그러므로 다중이 되는 것이고, 인터페이스끼리만 상속이 가능 한 것이다.
  • 작성법 :
    interface 이름{
    	[public static final] 타입 상수명 = 값;
        [public abstract] 반환타입 메서드명([매개변수]);
    }
    • 메서드에서는 static쓰면 안된다. 왜냐하면 static은 바로 쓸 수 있게 해주는 건데 구현부가 없으므로 바로 사용을 할 수가 없으니 static쓰면 에러.
    • 메서드 public abstract 는 생략가능하다. (무조건 public abstract이기 때문. )
    • 메서드 오버라이드할 때 public 꼭 기억하고 붙일 것. 부모보다 접근제한자 범위가 좁으면 안되는데 기본값은 default이기 때문.
    • 멤버변수는 public static final 이어야 한다. 무조건 붙여야하니까 생략 가능.
      값을 변경할 수 없다. (상수)
      변수명은 가능하면 대문자로놓기 (상수, final이니까)

인터페이스의 구현

  • 상속이라는 뜻과 동일
  • '클래스가 인터페이스를 구현한다.' 라고 말한다.
  • extends 키워드대신 implements(구현) 키워드를 사용하며, 인터페이스를 구현한다고 한다.
    class AA implements A{} -> 클래스 AA는 인터페이스 A를 구현하는 클래스라는 뜻.
  • implements는 다중으로 사용할 수 있다.

인터페이스 사용

  • 같은 부모를 상속하고 있을 때 다형성을 활용할 수 있는데, 만약 각자 다른 부모를 상속하고 있을 때도 다형성을 활용하고 싶을 때 사용한다.
  • 인터페이스는 연결고리와 같은 기능을 한다.
    interface I{
    	void tmp();
    }
    class A implements I{
    	public void tmp(){
      	System.out.println("A");
      }
    }
    class B implements I{
    	public void tmp(){
      	System.out.println("B");
      }
    }
    class AA extends A{
    	public void tmp(){
      	System.out.println("AA");
      }
    }
    class BB extends B{
    	public void tmp(){
      	System.out.println("BB");
      }
    }
    public class Main{
    	public static void main(String args[]){
      	Main main = new Main();
          main.run(new AA());
          main.run(new BB());
      }
      void run(I a){
      	a.tmp();
      }
    }
    이렇게 사용해야 한다.
    Interface를 부모가 상속하고 자식이 부모를 상속해서 Interface에 있는 메서드를 각자 다른 부모를 상속하고 있는 자식들이 공통적으로 사용할 수 있게 한다.

인터페이스를 이용한 다형성

class AA{
	void tmp(BB bb){
    	bb.tmp();
    }
}
class BB{
	void tmp(){
    	System.out.println("BB");
    }
}
class CC{
	void tmp(){
    	System.out.println("CC");
    }
}
public class Main{
	public static void main(String[] args){
    	AA a = new AA();
        a.tmp(new BB());
    }
}
  • 위와같이 코드를 짜면 A가 B에 강하게 의존(Dependency)하고 있다.
    B가 변경되면 A가 에러가 난다.
  • B대신 C를 A에서 사용하고 싶으면 A클래스의 tmp메서드의 인자(매개변수)도 C로 바꿔줘야 한다.
interface I{
	public abstract void tmp();
}
class AA{
	void tmp(I i){
    	bb.tmp();
    }
}
class BB implements I{
	void tmp(){
    	System.out.println("BB");
    }
}
class CC implements I{
	void tmp(){
    	System.out.println("CC");
    }
}
public class Main{
	public static void main(String[] args){
    	AA a = new AA();
        a.tmp(new BB());
    }
}
  • 기존방식은 A클래스에 무조건 한 종류의 클래스만 인자로 받았어야 하는데, 그러면 수정할 때마다 인자의 타입을 바꿔주고, 보내는 main의 매개변수도 바꿔줘야 한다. (일일히 다 신경써야 한다. )
  • 그래서 인터페이스를 선언부만 만들고, 그 인터페이스를 이용해서 B나 C를 구현하면 (다형성 개념) A메서드에서 인터페이스를 인자로 받게 해놓고, main에서는 인터페이스를 구현한 자식클래스 (B, C)를 매개변수로 보내면 A를 별도로 수정할 필요가 없다.
  • BB나 CC는 인터페이스를 구현했기 때문에 AA의 tmp()에 보낼 수 있다.

DI (Dependency Injection)

  • 느슨한 결합
  • 의존성을 낮추기 위함.
  • 중간다리를 놔서 에러가 나도 중간다리만 에러가 나게 한다.
class AA{
	void tmp(){
    	BB bb = new BB();
    	bb.tmp();
    }
}
class BB{
	void tmp(){
    	System.out.println("BB");
    }
}
public class Main{
	public static void main(String[] args){
    	AA a = new AA();
        a.tmp();
    }
}
  • 위와같이 A에서 직접 B를 불러서 사용하면 Injection이 아니다.
    이렇게 하면 B를 직접 불러서 쓸 때 오류가 나면 A에서 바로 터진다.
class AA{
	void tmp(BB bb){
    	bb.tmp();
    }
}
class BB{
	void tmp(){
    	System.out.println("BB");
    }
}
class CC{
	void tmp(){
    	System.out.println("CC");
    }
}
public class Main{
	public static void main(String[] args){
    	AA a = new AA();
        a.tmp(new BB());
    }
}
  • 위와같이 Main이라는 중간다리에서 B를 생성해서 A에게 보내고 A에서 실행을 하게 되면 만약 터져도 A가 터지지 않고 Main이 터지게 된다.
  • 이렇게 의존성을 조금 줄여서 사용하는 것이 좋다.
profile
계속 나아가기

0개의 댓글