[JAVA] 인터페이스

msung99·2022년 4월 11일
0
post-thumbnail

오늘나가는 것까지 시험범위
토요일 1시에 비대면 시험


지난내용 복습

업캐스팅

parent p  = new child();

자식클래스에서 func() 이라는 함수를 오버라이딩을 하고, p.func() 를 호출하면 오버라이딩 된 녀석이 호출된다.


다형성 vs 일반 상속

반면 다형성이 아니라, 그냥 일반 상속 구조를 생각해보자.
부모 클래스에 있는 멤버를 상속받고, 오버라이딩을 안하면 내가 물려받은 부모의 메소드 func() 가 실행된다.


다중상속의 한계

  • (죽음의 다이아몬드) : 다중 상속(부모가 여렷일때)을 받은 클래스의 어떤 특정 메소드가 어떤 부모로 부터 온 메소드인지 판단하기 힘들다.

    ex) 최상위 계층의 부모에 있는 메소드 func를 다음 부모들이 오버라이딩하고, 그 메소드 func 를 자식 클래스가 상속받는 경우
    => 자식 클래스는 어떤 func 함수를 물려받아야 할지 알 수 없다.

  • 추상 메소드를 여러개 상속(다중 상속)받아도 문제되지 않는다.

    • Why?
      두 추상 메소드는 정의부가 없으므로, 즉 정의부가 동일하며 선언부 또한 동일하다. 땨랴셔 그냥 오버라이딩된 두 추상 메소드는 완전히 똑같은 메소드이므로 어떤 것을 상속받아도 상관x
      => 다중 상속의 한계점을 추상 메소드가 극복!!

추상 메소드는 다중 상속이 가능하다


인터페이스

인터페이스 = 추상 메소드만 선언하는 추상 클래스. 다중 상속이 가능하다

  • 이로써 다중 상속이 가능해짐

  • 사실 추상 메소드말고도 다른 멤버도 가짐.

  • 인터페이스 구성요소

    • 추상메소드
    • default 메소드
    • static 메소드
    • static final 상수
      => 이들의 공통점 : 다중 상속을 하더라도 문제가 없는 애들
  • 상수가 그냥 final 이였다면, 클래스로부터 객체가 만들어졌을때 각 객체별로 다른 값을 가질수있다. 이런 경우에 나누어졌다 합쳐지면 문제 발생할수o


인터페이스 선언

  • 클래스 이름 대신에 인터페이스 이름 넣으면 선언끝!
public interface my_interface{
  int max_volumne = 10;  // => pulibc static final 로 나중에 자동으로 초기화됨
}

구성 멤버

  • 생성자가 없다!!!

    • 생성자라는 개념 자체가 없다.
    • 인터페이스는 객체를 만들수없기때문.
    • 인터페이스는 위에서 언급했듯, 추상메소드만 가지는 추상 클래스와 같은 개념이기 때문
  • 필드

    • 일반 필드는 없다. 그냥 int a; 이렇게 선언해도 public static final 가 컴파일 단계에서 자동으로 붙게됨
    • 그냥 일반 필드 int a 는 각 객체마다 존재하는 값이 생성되므로 다중상속시 문제가 발생함
  • 추상 메소드

  • 디폴트 메소드

    • 일반 상속관계에서 부모한테 상속받은 메소드이지만 오버라이딩 하지 않은 메소드
  • static 메소드


추상 메소드 선언

  • 인터페이스에서 추상 메소드 = 다형성에서의 추상 메소드

  • 이 놈을 상속받는 클래스에서 정의부를 만들고, 객체를 생성가능


디폴트 메소드

  • 함수 정의부 내용이 들어간 메소드

  • default 메소드임을 알려주는 "default" 키워드를 붙인다.
    (여기서 default 는 접근제한자가 아니다!!!)

  • 오버라이딩의 번거로움을 해결 (동일한 정의부에 대한 오버라이딩의 귀찮음을 해소)

    • ex) 인터페이스에서 추상 메소드를 정의하는데, 추상 메소드의 내용은 모든 클래스에서 100% 동일하게 동작해야 하는 경우

      => 매번 인터페이스로 부터 상속받은 각각의 클래스가 1000개 있을때, 각 클래스 안에 귀찮게 동일한 추상 메소드 정의부를 1000개 적어야한다. 이런 귀찮음을 해결해줌

  • 인터페이스에서의 디폴트 메소드는 오버라이딩을 꼭 하지 않아도 된다. (선택사항)

    • 오버라이딩을 할경우, 오버라이딩 된 녀석이 실행됨
    • 오버라이딩을 안하면 인터페이스에서 정의한 내용이 시행됨
      (일반 상속에서 다형성의 경우, 오버라이딩을 안했다면 에러가 발생했을거임)

  • 그림처럼 다중 상속을 받을때 양쪽에 오버라이딩된 디폴트 메소드가 있다면, 디폴트 메소드를 반드시!! 오버라이딩 해야함.
    • 왼쪽, 오른쪽 디폴트 메소드가 똑같다는 보장이 없기 때문에 오버라이딩을 해야함

정적 메소드 선언

  • 우리가 아는 static 메소드임

인터페이스 구현

  • 상속 : 부모 클래스 <- 자식 클래스
  • 인터페이스 : 인터페이스 <- 구현 클래스
    (동일한 맥락)

부모에 대응하는 것은 인터페이스고,
자식에 대응하는것은 구현 클래스이다.


구현 클래스 선언 형태

public class A implements B{

}

예제 분석

예제1

  • 추상 메소드를 하나라도 구현 클래스에서 정의안하면, 그 추상 클래스가 되는 것이고 abstract 키워드를 붙여줘야함

  • 인터페이스 타입의 변수(RemoteControl rc;) 를 만들고 ( = 다형성에서 부모 타입의 변수 생성),

  • 참조변수에 인터페이스를 탑제한(구현한) 실제 구현 클래스들의 객체를 할당할 수 있다 ( = 다형성에서 업케스팅. 부모 참조변수에 자식 객체 할당하는 것 )


상속 vs 인터페이스

  • 서로 다른 두 부모로 부터 상속받은 객체를 구현했는데, 이 두 객체에 대해 동일한 인터페이스를 추가로 탑제했다면 (같은 인터페이스를 추가적으로 구현했다면) 인터페이스 타입으로 업케스팅이 가능하다.

  • 즉, 각 객체는 각각의 다른 부모 타입으로 업케스팅이 가능하며, 동일한 인터페이스로도 업케스팅이 가능하다.

  • 각각의 자식 객체 안에는 각 부모에게 물려받는 멤버와, 동일한 인터페이스로 부터 구현된 멤버가 존재한다.

즉, 다른 상속 계층도에 있어서 전혀 연관없는 클래스 객체 A,B 를 동일한 인터페이스를 탑제하면, 두 객체 모두 해당 인터페이스 타입으로 업케스팅 가능해서 동일한 데이터 타입이 될수 있다.

=> 데이터 타입이 동일해 지면 배열로 처리도 가능해진다.


익명 객체

(다음 시간에 설명 자세히 진행. 아마 시험 범위 포함 안될듯?)

  • 굳이 클래스의 정의를 따로 만들지 않고, 1회성으로 임의의 객체를 만드는것
RemoteControl rc = new RemoteControl();

위처럼 인터페이스 참조변수에 구현 클래스 객체가 할당되는 것이 원래 정상이다.

  • 그런데 익명객체는 아래처럼 참조변수에 클래스 선언문을 할당하는 것이다.
RemoteControl rc = new RemoteControl(){
  public void turnOn() { "TV를 킴" }
  public void turnOff() { "끈다잉" }
  public void setVolume(int volume) { ~~~ }
};

특징

  • 이름이 없고 인터페이스를 탑제한 클래스이다.

  • 이름 대신에 어떤 인터페이스를 탑제하는지 인터페이스 이름을 적어준다

  • 안에 내용을 반드시 추상메소드의 구현 코드를 적어줘야한다!!!!

  • 일반적인 필드나 메소드를 포함해도 상관x. 단, 선언된 애들은 안에서 내부 연산을 위해서만 사용가능. 인터페이스 변수로 접근 불가능


인터페이스 구현

  • 인터페이스 다중으로 탑제(구현) 가능
    (애초에 인터페이스는 다중 상속을 위해 탄생한 개념이기 떄문)
pubic class RemoteControl implements inter1, inter2{
   인터페이스 inter1, inter2 에 대한 추상 메소드를 모두 구현해야함
}
  • 인터페이스를 다중 탑제한 구현 클래스는 탑제한 모든 인터페이스 타입으로 업캐스팅이 가능하다.

=> 즉, 일반 상속(다형성)에서의 업캐스팅 처럼
RemoteControl rc = new inter1(); 이 가능하고
RemoteControl rc = new inter2(); 도 가능하다.


다운 캐스팅

  • 상속 다형성과 완전히 동일. 인터페이스 타입으로 업캐스팅 후, 구현 클래스 타입으로 강제 형변환을 해야함.

  • instanceof 도 사용법 똑같음


인터페이스간 상속 가능

  • 인터페이스가 인터페이스를 상속할 수 있다.
  • 여러 개의 인터페이스 다중 상속 받을 수 있음
public interface inter1 extends inter2, inter3 {
   ...
}
  • inter1 인터페이스에 대한 구현 클래스를 만든다면, 3개의 인터페이스(inter1, inter2, inter3) 에 대한 추상 클래스를 모두 구현해야함

private 메소드

  • 인터페이스는 private 메소드도 가질 수 있다
  • 인터페이스 내부에서 연산을 하기위해 사용. 외부에서 접근 불가능

0개의 댓글