09009
[Java] 인터페이스 본문
인터페이스
• 일종의 추상클래스. 구현된 것은 아무것도 없는, 밑그림만 그려진 기본 설계도
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 |