본문 바로가기

BACKEND/JAVA

[이것이 자바다] 8장 인터페이스

* 인터페이스의 역할

객체의 사용 방법을 정의한 타입

객체의 교환성을 높여주기 때문에 다형성을 구현하는 매우 주용아한 역할을 한다.

자바 8의 람다식은 함수적 인터페이스의 구현 객체를 생성한다.

개발 코드가 인터페이스의 메소드를 호출하면 인터페이스는 객체의 메소드를 호출 시킨다.

개발 코드가 직접 객체의 메소드를 호출하면 간단한데, 왜 중간에 인터페이스를 두는지 의문점이 생길텐데 의문점을 해결할 이유는 개발 코드를 수정하지 않고, 사용하는 개체를 변경할 수 있도록 하기 위해서이다.

 

* 인터페이스 선언

class 키워드 대신 interface키워드 사용

접근제한자 dafual,public 가능하다.

// 예시
[ public ] interface 인터페이스면 { ... }

public interface RemoteControl{
	public void turnOn();
}

 

* 구현 클래스 선언

implements 키워드를 사용해 인터페이스를 구현한다.

public class Television implements RemoteControl{

    @Override
    public void turnOn() {
        System.out.println("Tv를 켜다.");
    }
}

 

* 상수 필드(Constant Field)

인터페이스는 객체 사용 설명서이므로 런타임 시 데이터를 저장할 수 있는 필드를 선언할 수 없다.

상수 필드는 선언할 수 있으므로 인터페이스에 선언된 필드는 모두 public static final 상수 특성을 갖는다.

상수를 선언할 때는 반드시 초기값을 대입해야 한다.

 

* 추상 메소드(Abstract Method)

객체가 가지고 있는 메소드를 설명한 것으로 호출할 때 어떤 매개값이 필요하고, 리턴 타입이 무엇인지 알려준다.

실제 실행부는 객체(구현 객체)가 가지고 있다.

public interface RemoteControl {
	// 상수 필드
    int MAX_VOLUME = 10;
    int MIN_VOLUME = 0;

    public void turnOn(); // 추상 메서드
}

 

* 디폴트 메소드(Default Method)

인터페이스에 선언되지만 사실은 객체(구현 객체)가 가지고 있는 인스턴스 메소드라고 생각해야 하며 defualt 키워드가 리턴 타입 앞에 붙는다.

기존 인터페이스를 확장해서 새로운 기능을 추가하기 위하여 자바 8에서 탄생했다.

interface RemoteControl{
	// 디폴트 메소드
    default void setMute(boolean mute){
    	if(mute){
        System.out.println("무음 처리");
        } else {
        System.out.println("무음 해제");
        }
    }
}

 

* 정적 메소드(Static Method)

구현 객체가 없어도 인터페이스만으로 호출할 수 있다.

 

* 다중 인터페이스 구현 클래스

public interface RemoteControl {
    void turnOn();
    void turnOff();
}
public interface Searchable {
    void search(String url);
}
public class SmartTelevision implements RemoteControl, Searchable{
    @Override
    public void turnOn() {
        System.out.println("Tv를 켜다");
    }

    @Override
    public void turnOff() {
        System.out.println("Tv를 끄다");
    }

    @Override
    public void search(String url) {
        System.out.println(url + "을 검색하다");
    }
}
public class MultiInterfaceImplEx {

    public static void main(String[] args) {
        RemoteControl rc = new SmartTelevision();
        rc.turnOn();    // Tv를 켜다
        rc.turnOff();   // Tv를 끄다

        Searchable searchable = new SmartTelevision();
        searchable.search("https://tistory.com/");     // https://tistory.com/ 검색
    }
}

 

* 인터페이스 상속

public interface InterfaceC extends InterfaceA, InterfaceB{

    void methodC();
}

 

* 자동 타입 반환(Promotion)

인터페이스 변수 = 구현 객체;
// 구현 객체 -> 변수 (자동 타입 변환)

부모 클래스가 인터페이스를 구현하고 있다면 자식 클래스도 인터페이스 타입으로 자동 타입 변환될 수 있다.

자동 타입 변환

 

* 필들의 다형성

필드 타입으로 인터페이스를 선언하면 필드값으로 다양한 구현 객체를 대입할 수 있다(자동 타입 변환)

// Tire.java
public interface Tire {
    void roll();
}
// HankookTire.java
public class HankookTire implements Tire{

    @Override
    public void roll() {
        System.out.println("한국 타이어가 굴러갑니다.");
    }
}
// KumhoTire.java
public class KumhoTire implements Tire {
    @Override
    public void roll() {
        System.out.println("금호 타이어가 굴러갑니다.");
    }
}
// Car.java
public class Car {
// 필드
    Tire  tire = new HankookTire();
        void run() {
        tire.roll();
    	}
}
public class CarEx {
    public static void main(String[] args) {
        Car car = new Car();
        car.run();  // 한국 타이어가 굴러갑니다.

        car.tire = new KumhoTire();
        car.run();  // 금호 타이어가 굴러갑니다.
    }
}

 

 

* 매개변수의 다형성

매개변수 타입을 인터페이스로 선언하면 메서드 호출 시 다양한 구현 객체를 대입할 수 있다.(자동 타입 변환)

// Vehicle.java
public interface Vehicle {
    void run();
}
// Bus.java
public class Bus implements Vehicle{
    @Override
    public void run() {
        System.out.println("버스가 달린다.");
    }
    public void checkFare() {
        System.out.println("승차요금을 확인한다.");
    }
}
// Taxi.java
public class Taxi implements Vehicle{
    @Override
    public void run() {
        System.out.println("택시가 달린다.");
    }
}
// Driver.java
public class Driver {

    void drive(Vehicle vehicle) {
        vehicle.run();
    }
}
public class DriverEx {

    public static void main(String[] args) {
        Driver driver = new Driver();
        driver.drive(new Bus());    // 버스가 달린다.
        driver.drive(new Taxi());   // 택시가 달린다.
    }
}