09009

[Java] 인터페이스 본문

Back-End/JAVA
[Java] 인터페이스
09009

인터페이스

• 일종의 추상클래스. 구현된 것은 아무것도 없는, 밑그림만 그려진 기본 설계도

interface 인터페이스명 {
    public static final 타입 상수이름 = 값;
    public abstract 반환타입 메서드(매개변수 이름);
}

인터페이스의 작성 및 구현

  • 모든 멤버변수는 public static final이어야 한다. public static final은 생략할 수 있다.
    → static: 객체를 생성하지 않고 바로 사용 가능
    → final: 값을 변경할 수 없다.
  • 모든 메서드는 public abstract이어야 한다. public abstract는 생략할 수 있다. → 선언부는 있지만 구현부가 없다.
  • Java 1.8부터는 default / static으로 시작하는 메서드를 구현할 수 있다.
  • 인터페이스는 인터페이스로부터만 상속받을 수 있다. 인터페이스는 다중상속이 가능하여 여러 개의 인터페이스로부터 상속을 받는 것이 가능하다.

interface는 abstract class라고 생각하면 된다
interface는 abstract 메서드만 정의할 수 있다.
interface는 메서드 선언만 가능, 구현 불가능
인터페이스명은 형용사로 많이 사용한다.

class 클래스명 implements 인터페이스  // 인터페이스는 다중 구현 가능
interface 인터페이스명 extends 인터페이스,... // 인터페이스는 다중 상속 가능

 

  • 인터페이스는 추상클래스처럼 그 자체로는 객체를 생성할 수 없다.
  • 인터페이스는 객체 생성은 불가능하나 선언은 가능하다.
  • 인터페이스에 선언된 변수는 값을 변경할 수 없다.
    → 변수 앞에 public static final이 생략되었기 때문이다.
  • 인터페이스에서 선언된 변수는 static이 생략되어 있기 때문에 객체를 생성하지 않고 바로 사용할 수 있다.
  • 구현해야 하는 인터페이스의 메서드 중 일부만 구현할 경우, abstract를 작성하여 추상클래스로 선언해야 한다.
  • 상속과 구현을 동시에 하는 것이 가능하다.
  • 인터페이스를 구현하는 클래스는 인터페이스에 있는 메서드를 반드시 모두 재정의하여야 한다.

예제 소스코드

✍ Inter1.java

package ch08;
interface A1 { // 인터페이스는 객체를 생성할 수 없다.
	int K = 7 ; // int K 앞에 사실은 public static final이 생략된 것이다. 값 변경 불가
	void m1(); // void m1 앞에 사실은 public abstract가 생략된 것이다. 구현부가 없다.
	void m2();
}

class A2 implements A1 { // 인터페이스를 사용하기 위해서는 implements 구현한 클래스로 사용
	@Override
	public void m1() {
		System.out.println("안녕하세요");
	}
	@Override
	public void m2() {
		System.out.println("반가워요");
	} 	
}

public class Inter1 {
	public static void main(String[] args) {
//		A1 a = new A1(); // 에러 발생 -> 인터페이스는 객체 생성 불가
	    A1 a1 = new A2();	// 생성은 안되지만 선언은 가능
	    A2 a2 = new A2();
	    a1.m1(); a1.m2(); a2.m1(); a2.m2();
//	    a1.K = 88; 이렇게 적으면 에러 발생 -> final이므로 수정 불가능하기 때문
	    System.out.println("K = " + A1.K); // static이 생략되어 있어서 바로 쓸 수 있다.
	    System.out.println("K = " + a1.K);
	}

}

💻 출력 결과

안녕하세요
반가워요
안녕하세요
반가워요
K = 7
K = 7

 

 Inter2.java

package ch08;

interface B1 {
	int K1 = 10;
	void m1();
}

interface B2 extends B1 {
	void m2();
}

interface B3 {
	void m3();
}

interface B4 extends B2,B3 {
	void m4();
}

class B5 implements B4 {
	@Override
	public void m2() {
		System.out.println("감사해요");
	}
	@Override
	public void m1() {
		System.out.println("안녕하세요!");
	}
	@Override
	public void m3() {
		System.out.println("잘 있어요");
	}

	@Override
	public void m4() {
		 System.out.println("다시 만나요~");
	}
	
}
public class Inter2 {
	public static void main(String[] args) {
		B5 b = new B5();
		b.m1();
		b.m2();
		b.m3();
		b.m4();
                System.out.println("K1 = " + B5.K1);
	
	}

}

💻 출력 

안녕하세요!
감사해요
잘 있어요
다시 만나요~
K1 = 10

해설

  • 클래스 B5는 인터페이스 B4를 구현한다.
  • 인터페이스를 구현하는 클래스는 인터페이스에 있는 메서드를 반드시 모두 재정의하여야 한다. → 인터페이스에서 선언된 모든 메서드는 public abstract가 생략되어 있다.
  • 클래스 B5 → 인터페이스 B4 구현 → B4는 인터페이스 B2,B3를 상속받음. → B2는 인터페이스 B1을 상속받음.
    → 즉, 클래스 B5는 B1,B2,B3,B4에 있는 메서드를 모두 재정의하여야 한다.

실습 예제

 

✍ RemoteControl.java

// !!!! 인터페이스는 바로 사용할수 없다. 인터페이스를 구현하는 클래스가 있어야한다. !!!!
public interface RemoteControl {
//	interface의 상수는 public static final이 생략된 것이기 때문에 대문자를 쓴 것이다. -> 바뀔 수 없는 데이터
	int MAX_VOLUME = 10;
	int MIN_VOLUME = 0;
//	interface의 메서드는 public abstract가 생략된 것이다.
	void turnOn();
	void turnOff();
//	default method는 구현부를 만들 수 있다
	default void setMute(boolean mute) {
		if (mute) System.out.println("무음 처리합니다");
		else System.out.println("무음을 해제합니다.");
	}
//	static method도 구현부를 만들 수 있다
	static void changeBattery() {
		System.out.println("건전지를 교환합니다");
	}
}

 Tv1.java

// !!! 추상클래스, 인터페이스는 직접 객체를 생성할 수 없으므로 인터페이스를 구현한 클래스를 통해서 객체 생성 !!!!
public class Tv1 implements RemoteControl{
    @Override
    public void turnOn() {
        System.out.println("TV를 켭니다");
    }
    @Override
    public void turnOff() {
        System.out.println("TV를 끕니다");
    }
}

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

 RemoConEx1.java

public class RemoConEx1 {
    public static void main(String[] args) {
        RemoteControl[] rc = {new Tv1(), new Radio1()};
        for(int i = 0; i < rc.length; i++) {
            rc[i].turnOn();
            rc[i].turnOff();
            rc[i].setMute(false);
            RemoteControl.changeBattery();
            System.out.println("최대 볼륨 : " + RemoteControl.MAX_VOLUME);
            System.out.println("최소 볼륨 : " + RemoteControl.MIN_VOLUME);
        }
    }

💻 출력

TV를 켭니다
TV를 끕니다
무음을 해제합니다
건전지를 교체합니다
최대 볼륨 : 10
최소 볼륨 : 0
라디오를 켭니다
라디오를 끕니다
무음을 해제합니다
건전지를 교체합니다
최대 볼륨 : 10
최소 볼륨 : 0

 

!!! 추상클래스와 인터페이스는 직접 객체를 생성할 수 없다. 
    하지만 그 추상클래스와 인터페이스를 구현하는 클래스를 작성한 후에는 그 클래스를 통해서 객체를 생성할 수 있는 것이다. !!!


예제

 

✍ 입력

package exercises;

interface Printable {
    public void print(String doc);
//    public void colorPrint(String doc, String color);
}
// 인터페이스도 상속을 받을 수 있음
interface ColorPrintable extends Printable {
    public void colorPrint(String doc, String color);
}
class Printer implements Printable {
    @Override // 이 아래 메서드는 오버라이딩하는 메서드임을 컴파일러에게 알려주는 annotation. 컴파일러는 체크해서 문제가 있으면 알려준다
    public void print(String doc) {
        System.out.println(doc);
    }
}

class SPrinter implements Printable {
    @Override 
    public void print(String doc) {
        System.out.println("삼성 프린터");
        System.out.println(doc);
    }
}

class SPrinter2 implements ColorPrintable {
    @Override 
    public void print(String doc) {
        System.out.println("삼성 프린터");
        System.out.println(doc);
    }

    @Override
    public void colorPrint(String doc, String color) {
        System.out.println("삼성 프린터");
        System.out.println(color + "색으로");
        System.out.println(doc);
    }
}

class LPrinter implements Printable {
    @Override 
    public void print(String doc) {
        System.out.println("LG 프린터");
        System.out.println(doc);
    }
}

public class PrintableInterface {
    public static void main(String[] args) {
//        Printable prn = new Printer();
//        prn.print("Hello");

        String myDoc = "안녕하세요.";

        Printable prn1 = new SPrinter();
        prn1.print(myDoc);

        Printable prn2 = new LPrinter();
        prn2.print(myDoc);

        ColorPrintable prn3 = new SPrinter2();
        prn3.colorPrint(myDoc, "파랑");
    }
}

💻 출력

삼성 프린터
안녕하세요.
LG 프린터
안녕하세요.
삼성 프린터
파랑색으로
안녕하세요.

 

 

!! 기존 인터페이스에 새로운 기능(메서드)을 추가하고 싶을 때 

그 인터페이스를 직접 수정하면 기존 인터페이스를 구현한 클래스들은 에러가 발생한다.


왜냐하면 기존 인터페이스를 구현하였던 클래스들은

수정한 인터페이스의 추가한 새로운 메서드를 또 오버라이딩해야하는데 그렇지 않은 상태이기 때문이다.

 

그러므로 기존 인터페이스를 상속한 채 새로운 인터페이스를 생성하고 활용하는 것이 훨씬 수월하다. !!

 

위의 소스코드에서 Printer 클래스와  SPrinter 클래스는 Printable 인터페이스를 구현하였다.

이 클래스들은 Printable 인터페이스의 기존 메서드 print()를 오버라이딩하였다.

 

그런데 Printable 인터페이스에 새로운 메서드 colorPrint()를 추가하자마자 에러가 발생한 것을 확인할 수 있다.

위에서 언급하였던 것처럼 기존 인터페이스를 구현하였던 클래스들은 수정한 인터페이스의 추가한 새로운 메서드를 또 오버라이딩해야하는데 현재는 그렇지 않은 상태이기 때문이다.

 

그러므로 아래와 같이 새로운 기능(메서드)을 추가하고 싶을 때

기존 인터페이스에 메서드를 추가하는 것보다 새로운 인터페이스를 생성하고 활용하는 것이 훨씬 수월하다.

 

 

/

5/7

 

'Back-End > JAVA' 카테고리의 다른 글

[Java] 예외처리  (0) 2023.04.06
[Java] 추상클래스  (0) 2023.04.06
[Java] StringBuilder의 간단한 개념  (0) 2023.04.05
[Java] length, length(), size()  (0) 2023.04.05
[Java] JDBC (3) - 조회 / 입력 / 수정 / 삭제  (0) 2023.03.26