8.1 인터페이스 역할
사전적 의미로 두 장치를 연결하는 접속기를 말함
두 장치를 서로다른 객체로 본다면, 인터페이스는 두 객체를 연결하는 역할을 한다
예로)
객체 a가 객체b를 직접 사용한다면, 객체 a가 객체c를 사용하려면 소스코드를 변경하는 작업이 필요함
-> 인터페이스를 객체사이에 사용한다면
객체 a는 인터페이스의 메소드만을 사용하기 때문에, 객체b 든 객체 c든 관심이 없다
이렇게 객체 교체로 '다형성' 구현할 수 있다
다형성 구현 사용빈도 : 인터페이스 >> 상속
8.2 인터페이스와 구현 클래스 선언
인터페이스 물리적 형태는 클래스와 동일하다 ( .java 형태의 소스파일 작성 -> .class 형태로 컴파일)
클래스와 다른점 : 선언방법, 구성멤버
인터페이스 선언 :
interface 인터페이스명{...} // default 접근제한자 : 같은패키지 내부만
public interface 인터페이스명{...} // piblic 접근제한자 : 다른패키지도
중괄호 안에 인터페이스가 가지는 멤버를 선언할 수 있다
인터페이스가 가지는 멤버의 종류
public interface 인터페이스명{
public 상수 필드
public 추상 메소드
public 디폴트 메소드
public 정적 메소드
private 메소드
private 정적 메소드
}
추상메소드 : 선언부만 가짐 , 실행부는 자식 클래스에서 반드시 작성필요
구현 클래스 선언 :
객체 a가 -> 인터페이스의 추상 메소드를 호출하면 -> 인터페이스는 객체b의 메소드를 실행
그렇다면,
객체b(구현클래스,객체)는 인터페이스에 선언된 추상 메소드와 동일한 선언부를 가져야함(재정의,오버라이딩)
여기서 객체b를 인터페이스를 구현한(implement) 객체라고 한다..
객체b는 인터페이스에서 선언한 추상메소드에 대한 실행부가 구현되어있기 때문이다!
/ 객체b와 같은 구현객체는 인터페이스를 구현하고 있음을 선언부에 명시해야함 implement
public class B implements 인터페이스명{...}
/ implements 키워드의 뜻 :
해당 클래스가 인터페이스를 통해 사용할 수 있으며, 인터페이스의 추상메소드를 재정의한 메소드를 가진다는 뜻이다
/ 변수 선언과 구현 객체 대입
인터페이스도 하나의 타입, 변수의 타입으로 사용가능하다
RemoteControl rc;
RemoteControl rc = null; // 참조하는 객체가 없다는 뜻으로 null 사용가능
인터페이스를 통해 구현 객체를 사용하려면
-> 인터페이스 변수에 구현한 객체를 대입해아한다 (정확히는 구현객체의 번지를 대입)
rc = new Television();
인터페이스 변수에 구현객체가 대입되었다면, 해당 변수로 인터페이스의 추상메소드를 호출할 수 있다
rc.turnOn();
여기서 turnOn()메소드가 실행되면, 실제로 실행되는 것은 구현객체에서 재정의된 추상메소드 이다.
위에거 합쳐서
RemoteControl rc = new Television();
rc.turnOn();
또다른 구현객체 Audio 있다면, 객체교체해버리면
RemoteControl rc = new Audio();
rc.turnOn();
위 아래 실행결과 다름
8.3 상수 필드
인터페이스는 public static final 특성을 갖는 불변의 상수 필드를 멤버로 가질 수 있음
[public static final] 타입 상수명 = 값;
인터페이스에 선언된 필드는 모두 public static final 특성을 갖는다 왜??
(생략해도 컴파일과정에서 붙음)
상수명은 대문자로, 서로다른단어 연결 _ 로
상수는 구현객체와 상관없는 인터페이스의 소속멤버이다 -> 인터페이스로 바로접근 가능함!
8.4 추상 메소드
인터페이스는 구현클래스가 재정의 해야하는 public 추상메소드를 멤버로 가질 수 있음
추상메소드 : 선언부( 리턴타입,메소드명,매개변수) 만 가지고, 실행부{ } 없음
public abstract 붙이지 않아도 컴파일시 자동으로 메소드에 붙임 왜??
[public abstract] 리턴타입 메소드명 ( 매개변수,...);
구현클래스에서 인터페이스의 추상메소드를 재정의 할 때 주의할점 :
인터페이스의 추상메소드는 기본적으로 public 접근 제한을 가지므로,
더 낮은 접근제한으로 재정의 불가능하다!
그래서 구현 클래스에서 재정의한 메소드들 public 접근제한 추가되어잇다..
왜??
8.5 디폴트 메소드
인터페이스에 완전한 실행 코드를 가진, 디폴트메소드 선언할 수 있음
(선언부 실행부 모두가짐)
선언방법 :
default 접근제한자 리턴타입 앞에 붙는거 말고 클래스 메소드와 동일
[public] default 리턴타입 메소드명(매개변수,...){...}
디폴트 메소드의 실행부에는
상수필드를 읽거나,
추상 메소드를 호출하는 코드 작성할 수 있다..
. 디폴트 메소드는 구현객체가 필요하다!
->
디폴트 메소드를 호출하려면
디폴트 메소드를 가지는 인터페이스의 변수에, 인터페이스의 구현객체가 대입되고
그 변수를 통해 디폴트 메소드를 호출해야 한다..!
.. 구현클래스는 필요에 맞게 디폴트 메소드 수정도 가능하다
->
주의점 : public 접근 제한자를 반드시 붙이고 default 접근제한자 생략해야한다
8.6 정적 메소드
인터페이스에 정적메소드 선언 가능하다
추상메소드와 디폴트 메소드는 구현객체가 필요함
정적메소드는 인터페이스 만으로 호출가능! ( 인터페이스명.정적메소드명() )
선언방법 : 정적 메소드와 완전 동일
static 리턴타입 메소드명(매개변수,...){...}
정적메소드의 실행부 :
인터페이스의 상수필드는 읽릉 수 있지만
추상메소드, 디폴트 메소드, private메소드 호출할 수없다 ( 구현객체 필요한 메소드들 이기때문)
인터페이스의 상수필드 / 추상 메소드 / 디폴트 메소드 / 정적 메소드 모두 public 접근제한을 가진다
( 생략하더라도 컴파일 과정에서 public 붙는다 ) (이유 : 어디서든 접근 가능하게 하기위함??)
-> 인터페이스에 외부에서 접근할 수 없는 private 메소드 선언도 가능함!!
private 메소드 : 디폴트 메소드(실행부가지는) 안에서만 호출이 가능!
private 정적 메소드 : 디폴트 메소드 + 정적 메소드 안에서도 호출 가능!
private 메소드 사용이유 : 디폴트 메소드 & 정적 메소드의 중복코드 줄이기 위함
구현객체는 여러개 인터페이스 implements 가능 ( 다중 구현 가능? ... 클래스의 다중 상속은 불가능 했다)
구현객체는 다중 구현한 인터페이스들의 추상메소드를 모두 재정의 해야함!
구현객체는 다중 구현한 인터페이스들의 타입의 변수에 각각 대입될 수 있음
인터페이스간에도 상속 가능하다!
클래스와 달리 인터페이스는 다중 상속이 가능함..
public interface 자식인터페이스 extends 부모인터페이스1, 부모인터페이스2{...}
자식 인터페이스의 구현객체 :
자식 인터페이스 + 부모 인터페이스 의 추상메소드 모두 재정의 해야한다!
또한, 부모 인터페이스 타입의 변수에 자식 인터페이스의 구현객체가 대입될 수 있다
인터페이스의 타입변환은 인터페이스와 구현 클래스 간에 발생
인터페이스 변수 = 구현객체;
구현객체의 자식객체도 인터페이스 변수로 자동타입변환 가능함
자동타입변환된 인터페이스 변수는, 인터페이스에 선언된 메소드만 사용가능함
기호를 사용해서 인터페이스 타입을 -> 구현 클래스 타입으로 변환
구현클래스 변수 = (구현클래스) 인터페이스 변수;
자동타입변환된 인터페이스 변수가 구현객체의 메소드까지 호출하고싶다면, 강제타입변환으로
원래 구현객체의 타입으로 변환해야한다
인터페이스는 다형성 구현하기 위한 주된 기술로 사용된다
상속의 다형성과 마찬가지로 인터페이스의 다형성도 다형성을 구현하기 위해,
재정의와 자동타입변환 기능을 이용한다..
상속에서는 부모클래스타입에 자식 객체들을 대입해서 다형성을 구현
인터페이스는 인터페이스타입에 구현 객체들을 대입해서 다형성을 구현
상속에서는 매개변수 타입을 부모타입으로 선언하고 호출할때 다양한 자식객체를 대입했다
인터페이스에서는 매개변수 타입을 인터페이스로선언하고 호출할때 다양한 구현객체를 대입함
-> 인터페이스를 구현하는 객체를 자동타입변환 없이 매개값으로 사용 ( 컴파일시 자동타입변환됨 )
상속에서 : instanceof 이용해 객체의 타입을 확인함
인터페이스에서도 마찬가지
인터페이스 instanceof 객체 // boolean타입으로 값나옴