8.1 인터페이스 역할
인터페이스는 사전적 의미로 두 장치를 연결하는 접속기를 말한다. 여기서 두 장치를 서로 다른 객체로 본다면, 인터페이스는 이 두 객체를 연결하는 역할을 한다.
![](https://velog.velcdn.com/images/namsm17/post/3fa14144-74ef-464c-aa97-417b18e08e31/image.png)
객체 A가 인터페이스의 메소드를 호출하면, 인터페이스는 객체B의 메소드를 호출하고 그 결과를 받아 객체 A로 전달한다.
8.2 인터페이스와 구현 클래스 선언
물리적 형태는 클래스와 동일하나 소스를 작성할 때 선언하는 방법과 구성 멤버가 클래스와 다르다.
인터페이스 선언
인터페이스 선언은 class 키워드 대신 interface 키워드를 사용한다. 접근 제한자로는 클래스와 마찬가지로 default, public 을 붙일 수 있다.
interface 인터페이스명 { ... }
public interface 인터페이스명 { ... }
중괄호 안에는 인터페이스가 가지는 멤버들을 선언할 수 있는데, 다음과 같은 종류가 있다.
public interface 인터페이스명 {
변수 선언과 구현 객체 대입
인터페이스도 하나의 타입이므로 변수의 타입으로 사용할 수 있다. 인터페이스는 참조 타입이므로 null 값을 대입할 수 있다.
인터페이스를 통해 구현 객체를 사용하려면, 인터페이스 변수에 구현 객체를 대입해야 한다. 정확히 말하면 구현 객체의 번지를 대입해야 한다.
인터페이스 변수에 구현 객체가 대입이 되었다면 변수를 통해 인터페이스의 추상 메소드를 호출할 수 있게 된다.
public class Television implements RemoteControl {
@Override
public void turnOn() {
System.out.println("TV를 켭니다.");
}
}
public class RemoteControlExample {
public static void main(String[] args) {
RemoteControl rc;
rc = new Television();
rc.turnOn();
}
}
8.3 상수 필드
public static final 특성을 갖는 상수 필드를 멤버로 가질 수 있다.
인터페이스에 선언된 필드는 모두 public static final 특성을 갖기 때문에 생략하더라도 자동적으로 컴파일 과정에서 붙게 된다.
8.4 추상 메소드
인터페이스는 구현 클래스가 재정의해야 하는 public 추상 메소드를 멤버로 가질 수 있다. 추상 메소드는 리턴 타입, 메소드명 , 매개변수만 기술되고 중괄호를 붙이지 않는 메소드를 말하며 public abstract를 생략하더라도 컴파일 과정에서 자동적으로 붙는다.
구현 클래스에서 추상 메소드 오버라이딩 시 주의해야할 점은 public이 기본 접근 제한이기 때문에 public보다 낮은 접근 제한으로 오버라이딩 불가하다.
구현 객체가 대입되면 인터페이스 변수로 추상 메소드를 호출할 수 있게 된다. 이때 어떤 구현 객체가 대입되었는지에 따라 실행 내용이 달라진다.
8.5 디폴트 메소드
인터페이스에는 완전한 실행 코드를 가진 디폴트 메소드를 선언할 수 있다. 추상 메소드는 실행부가 없지만, 디폴트 메소드는 실행부가 있다. 선언 방법은 클래스 메소드ㅇ와 동일, default 키워드가 리턴 타입 앞에 붙는다.
[public] default 리턴타입 메소드명(매개변수, ... ) { ... }
8.6 정적 메소드
인터페이에는 정적 메소드도 선언이 가능하다. 추상 메소드와 디폴트 메소드는 구현 객체가 필요하지만, 정적 메소드는 구현 객체가 없어도 인터페이스만으로 호출할 수 있다. 선언 방법은 클래스 정적 메소드와 완전동일.
[public | private] static 리턴타입 메소드명 ( 매개변수 , ... ) { ... }
8.7 private 메소드
인터페이스의 상수 필드, 추상 메소드, 디폴트 메소드, 정적 메소드는 모두 public 접근 제한을 갖는다. 이 멤버들은 선언시 public을 생략하더라도 컴파일 과정에서 자동적으로 붙는다. 인터페이스도 외부 접근 불가 private 메소드 선언이 가능하다.
구분 | 설명 |
---|
private 메소드 | 구현 객체가 필요한 메소드 |
private 정적 메소드 | 구현 객체가 필요 없는 메소드 |
private 메소드는 디폴트 메소드 안에서만 호출이 가능 private 정적 메소드는 정적 메소드 안에서도 호출이 가능 private 메소드의 용도는 디폴트와 정적 메소드들의 중복 코드를 줄이기 위함이다.
8.8 다중 인터페이스 구현
구현 객체는 여러 개의 인터페이스를 implements할 수 있다. 구현 객체가 인터페이스 A와 인터페이스 B를 구현하고 있다면, 각각의 인터페이스를 통해 구현 객체를 사용 가능하다.
public class 구현클래스명 implements 인터페이스 A, 인터페이스 B {
}
구현 객체가 어떤 인터페이스 변수에 대입되느냐에 따라 변수를 통해 호출할 수 있는 추상 메소드가 결정된다.
8.9 인터페이스 상속
인터페이스도 다른 인터페이스를 상속할 수 있으며 클래스와는 달리 다중 상속을 허용한다. 다음과 같이 extends 키워드 뒤에 상속할 인터페이스들을 나열하면 된다
public interface 자식 인터페이스 extends 부모1, 부모2 {
}
자식 인터페이스의 구현 클래스는 자식 인터페이스의 메소드뿐만 아니라 부모 인터페이스의 모든 추상 메소드를 재정의해야한다. 그리고 구현 객체는 자식 및 부모 인터페이스 변수에 대입될 수 있다.
자식인터페이스 변수 = new 구현클래스(...);
부모인터페이스1 변수 = new 구현클래스(...);
부모인터페이스2 변수 = new 구현클래스(...);
구현 객체가 자식 인터페이스 변수에 대입되면 자식 및 부모 인터페이스의 추상 메소드를 모두 호출할 수 있으나, 부모 인터페이스 변수에 대입되면 부모 인터페이스에 선언된 추상 메소드만 호출가능하다.
8.10 타입 변환
인터페이스의 타입 변환은 인터페이스와 구현 클래스 간에 발생하며 인터페이스 변수에 구현 객체를 대입하면 구현 객체는 인터페이스 타입으로 자동 타입 변환된다. 반대로 인터페이스 타입을 구현 클래스 타입으로 변환시킬 수 있는데, 이때는 강제 타입 변환이 필요하다.
자동 타입 변환
인터페이스 변수 = 구현 객체;
강제 타입 변환
강제 타입 변환은 캐스팅 기호를 사용해서 인터페이스 타입을 구현 클래스 타입으로 변환시키는 것을 말한다.
구현클래스 변수 = (구현클래스) 인터페이스변수;
구현 객체가 인터페이스 타입으로 자동 변환되면, 인터페이스에서 선언된 메소드만 사용이 가능하다.
8.11 다형성
현업에서는 상속보다는 인터페이스를 통해서 다형성을 구현하는 경우가 더 많다.
객체 B와 구현 객체 C 둘 중 어느 객체가 인터페이스에 대입되었느냐에 따라서 객체 A의 메소드 호출 결과는 달라질 수 있다.
인터페이스의 다형성은 상속과 마찬가지로 재정의와 자동 타입 변환기능을 이용한다. 인터페이스의 추상 메소드는 구현 클래스에서 재정의를 해야 하며, 재정의되는 내용은 구현 클래스마다 다르다. 구현 객체는 인터페이스 타입으로 자동 타입 변환이 되고, 인터페이스 메소드 호출 시 구현 객체의 재정의된 메소드가 호출되어 다양한 실행결과를 얻을 수 있다.
필드의 다형성
부모 타입 클래스 타입이 아니고 인터페이스라는 점에서 상속과 다르다.
매개변수의 다형성
메소드 호출 시 매개값을 다양화하기 위해 상속에서는 매개변수 타입을 부모 타입으로 선언하고 호출할 때에는 다양한 자식 객체를 대입했다. 이것은 자동 타입 변환 때문인데, 비슷한 원리로 매개 변수 타입을 인터페이스로 선언하면 메소드 호출 시 다양한 구현 객체를 대입할 수 있다.
8.12 객체 타입 확인
우리는 상속에서 객체 타입을 확인하기 위해 instanceof 연산자를 사용했는데, 인터페이스에서도 사용이 가능하다.
if ( vehicle instanceof Bus ) {
}
메소드의 매개변수가 인터페이스 타입일 경우, 메소드 호출 시 매개값은 해당 인터페이스를 구현하는 모든 객체가 될 수 있다. 만약 매개값이 특정 구현 객체일 경우에만 강제 타입 변환을 하고 싶다면 instanceof 연산자를 사용해서 매개값의 타입을 검사해야 한다. (Java 12 부터는 instanceof 연산의 결과가 true일 경우 우측 타입 변수를 사용가능 하기 때문에 강제 타입 변환이 필요없다.)
8.13 봉인된 인터페이스
무분별한 자식 인터페이스 생성을 방지하기위해 sealed 인터페이스를 사용가능하다. 나머지 내용은 상속과 같다.
확인문제
1. 1
2. 3
3. 4
4. 1,2,3,4
5.
implements Remocon,
@Override
public void powerOn() {
System.out.println("TV를 켰습니다.");
}
6.
public class Cat implemets soundable {
@Override
public String sound() {
return "야옹;"
}
}
public class Cat implemets soundable {
@Override
public String sound() {
return "멍멍;"
}
}
7.
public interface DataAccessObject {
public void select();
public void insert();
public void update();
public void delete();
}
public class OracleDao implements DataAccessObject {
@Override
public void select() {
System.out.println("Oracle DB에서 검색");
}
@Override
public void insert() {
System.out.println("Oracle DB에 삽입");
}
@Override
public void update() {
System.out.println("Oracle DB를 수정");
}
@Override
public void delete() {
System.out.println("Oracle DB에서 삭제");
}
}
public class MySqlDao implements DataAccessObject {
@Override
public void select() {
System.out.println("MySql DB에서 검색");
}
@Override
public void insert() {
System.out.println("MySql DB에 삽입");
}
@Override
public void update() {
System.out.println("MySql DB를 수정");
}
@Override
public void delete() {
System.out.println("MySql DB에서 삭제");
}
}
8. a instanceof C c