티스토리 뷰

8.1 인터페이스 역할

인터페이스는 두 객체를 연결하는 역할

사용되는 객체만을 변경하여 다양한 실행 결과를 얻을 수 있도록 함 = 다형성 구현에 주된 기술로 이용

 

8.2 인터페이스와 구현 클래스 선언

인터페이스 선언

interface 인터페이스 이름 { }
public interface 인터페이스 이름 {
    // 상수 필드
    // 추상 메소드
    // 디폴드 메소드
    // 정적 메소드
    // private 메소드
}

 

구현 클래스 선언

// 인터페이스
interface AInter { 
    void turnOn();
}

// 인터페이스를 구현한 객체
// 인터페이스의 추상 메소드를 재정의한 메소드가 있음
class BClass implements AInter {
    void turnOn(){
        /*구현부*/
    }
}

 

변수 선언과 구현 객체 대입

  • 인터페이스도 변수 타입으로 사용 가능
  • 참조 타입에 속하기 때문에 null대입 가능
public class InterfaceDemo {
    public static void main(String[] args) {
        RemoteControl remote;
        // 인터페이스를 통해 구현 객체를 사용하려면 구현 객체를 대입해야 한다.
        remote = new TV();
        // 변수를 통해 인터페이스의 추상 메소드를 호출할 수 있게 된다.
        // 실행되는 것은 오버라이딩된 메소드
        remote.turnOn(); // tv를 켭니다 출력

        // 다른 객체를 대입하면 대입된 객체의 오버라이딩된 메소드가 실행된다
        remote = new Audio();
        remote.turnOn(); // 오디로를 켭니다 출력

    }
}

interface RemoteControl {
    public void turnOn();
}

class TV implements RemoteControl {
    @Override
    public void turnOn(){
        System.out.println("tv를 켭니다");
    }
}

class Audio implements RemoteControl {
    @Override
    public void turnOn() {
        System.out.println("오디로를 켭니다");
    }
}

 

8.3 상수 필드

  • public static final 특성을 갖는 불변의 상수 필드를 멤버로 가질 수 있으며
  • 생략하더라도 자동적으로 컴파일 과정에서 붙게 된다.
interface AInter {
    // 대문자 + (_) 조합으로 사용
    int MAX_VOLUME = 10;
}

class main{
    main() {
        // 인터페이스에 접근해 바로 사용 가능
        AInter.MAX_VOLUME
    }
}

 

8.4 추상 메소드

  • public 추상 메소드를 멤버로 가질 수 있으며 public abstract를 생략하더라도 컴파일 과정에서 자동으로 붙게 된다.
  • 인터페이스의 추상 메소드는 기본적으로 public 접근 제한을 갖기 때문에 더 낮은 접근 제한으로 재정의할 수 없음

 

(코드는 8.2 참조)

 

8.5 디폴트 메소드

  • 완전한 실행 코드를 가진 디폴트 메소드 선언 가능 -> default 키워드를 사용
  • 상수 필드를 읽거나 추상 메소드 호출 가능
  • 구현 객체가 필요함
  • 디폴트 메소드를 구현 클래스에서 오버라이딩한 후에 사용 가능 -> default는 삭제하고 public 를 써야 한다.
public class InterfaceDemo2 {
    public static void main(String[] args) {
        RemoteControl2 remote;
        remote = new TV2();
        remote.setMut(); // 무음 처리 합니다 출력

        remote = new Audio2();
        remote.setMut(); // 오디오를 무음 처리 합니다 출력
    }
}

interface RemoteControl2 {
    default void setMut(){
        System.out.println("무음 처리 합니다");
    }
}

class TV2 implements RemoteControl2 {

}

class Audio2 implements RemoteControl2 {
    @Override
    public void setMut() {
        System.out.println("오디오를 무음 처리 합니다");
    }
}

 

8.6 정적 메소드

구현 객체가 없어도 인터페이스만으로 호출 가능

public 생략해도 자동으로 붙음

상수 필드 사용 가능하지만 구현 객체가 필요한 다른 것들은 호출 불가능

 

8.7 private 메소드

  • private 메소드는 디폴트 메소드 안에서만 호출 가능
  • private 정작 메소드는 디폴트 메소드 뿐만 아니라 정적 메소드 안에서 호출 가능
  • private 메소드는 디폴트와 정적 메소드의 중복 코드를 줄이기 위해 사용

 

8.8 다중인터페이스 구현

package beginnerJava.src.ch08;

public class InterfaceDemo3 {
    public static void main(String[] args) {
        // 어떤 인터페이스 변수에 대입되느냐에 따라 변수를 통해 호출할 수 있는 추상 메소드가 결정
        RemoteControl3 remote = new TV3();
        remote.turnOn();

        Searchable search = new TV3();
        search.search();
    }
}

interface RemoteControl3 {
    void turnOn();
}

interface Searchable {
    void search();
}

// 쉼표로 구분하고 인터페이스가 가진 모든 추상 메소드를 재정의해야함
class TV3 implements RemoteControl3, Searchable {
    @Override
    public void turnOn() {
        System.out.println("티비를 켭니다");
    }

    @Override
    public void search() {
        System.out.println("티비를 검색합니다");
    }
}

 

8.9 인터페이스 상속

public class InterfaceCImplDemo {
    public static void main(String[] args) {
        InterfaceCImpl i = new InterfaceCImpl();
        
        // 부모 인터페이스 변수에 대입되면 부모 인터페이스의 것들만 호출 가능
        InterfaceA ia = i;
        ia.methodA();
        // ia.methodB();
        
        InterfaceB ib = i;
        // ib.methodA();
        ib.methodB();
        
        // 자식 인터페이스 변수에 대입되면 부모 및 자식 인터페이스의 모든 것들 호출 가능
        InterfaceC ic = i;
        ic.methodA();
        ic.methodB();
        ic.methodC();
    }
}
 
// 부모 인터페이스이 모든 추상 메서드를 재정의해야 한다
class InterfaceCImpl implements InterfaceC {
    @Override
    public void methodA() {
        System.out.println("메소드A");
    }

    @Override
    public void methodB() {
        System.out.println("메소드B");
    }

    @Override
    public void methodC() {
        System.out.println("메소드C");
    }
}

interface InterfaceA {
    void methodA();
}

interface InterfaceB {
    void methodB();
}

// 다른 인터페ㅣ스 상속 가능
// 다중 상속 가능
interface InterfaceC extends InterfaceA, InterfaceB {
    void methodC();
}

 

8.10 타입 변환

자동 타입 변환: 인터페이스 변수 = 구현 객체

강제 타입 변환: 구현 변수 = (구현 클래스) 인터페이스 변수

public class CastingDemo {
    public static void main(String[] args) {
        // 자동 타입 변환
        Vehicle bus = new Bus();
        bus.run();
        // bus.stop(); 사용 불가능

        // 강제 타입 변환
        Bus bus2 = (Bus) bus;
        bus2.run();
        bus2.stop();
    }
}

interface Vehicle {
    void run();
}

class Bus implements Vehicle {
    @Override
    public void run() {
        System.out.println("버스가 달린다");
    }

    public void stop() {
        System.out.println("버스가 멈춘다");
    }
}

 

8.11 다형성

  • 사용 방법은 동일하지만 다양한 결과가 나오는 성질
  • 메소드 재정의 + 자동 타입 변환 -> 다형성

필드의 다형성

매개변수의 다형성

  • 매소드의 매개변수로 인터페이스 타입을 사용할 수 있고,
  • 매개변수 호출 시 다양한 구현 객체를 대입하여 (자동 타입 변환)
  • 구현 객체에 맞는 실행 결과를 얻을 수 있음 (메소드 재정의)

 

8.12 객체 타입 확인

  • 객체 타입을 확인하기 위해 instanceof 연산자 사용 가능

 

8.13 봉인된 인터페이스

(상속 참조)

 

최근에 올라온 글