인터페이스는 구현되지 않은 메서드들을 모아두고, 이를 특정 클래스에서 필요에 따라 구현하는 방식으로 사용됩니다. 아래는 기본 문법입니다:
interface 인터페이스명 {
// 상수
// 추상 메서드
}
class 클래스명 implements 인터페이스명 {
// 필드와 메서드 정의
// 반드시 구현해야 할 인터페이스의 메서드들
}
중요 사항: 인터페이스는 더 추상적인 형태의 클래스로 간주되며, JDK 7까지는 모든 메서드가 본체 없이 선언되어야 했습니다. 하지만 JDK 8부터는 인터페이스 내부에서 정적 메서드나 디폴트 메서드를 정의할 수 있게 되었습니다.
예제 코드
1. 기본 인터페이스 선언 및 구현
package com.example.interface_;
public interface UsbDevice {
void start();
void stop();
}
package com.example.interface_;
public class Camera implements UsbDevice {
@Override
public void start() {
System.out.println("카메라 작동 시작...");
}
@Override
public void stop() {
System.out.println("카메라 작동 종료...");
}
}
package com.example.interface_;
public class MobilePhone implements UsbDevice {
@Override
public void start() {
System.out.println("휴대폰 작동 시작...");
}
@Override
public void stop() {
System.out.println("휴대폰 작동 종료...");
}
}
package com.example.interface_;
public class MainApp {
public static void main(String[] args) {
UsbDevice camera = new Camera();
UsbDevice phone = new MobilePhone();
Computer computer = new Computer();
computer.connectDevice(phone);
computer.connectDevice(camera);
}
}
package com.example.interface_;
public class Computer {
public void connectDevice(UsbDevice device) {
device.start();
device.stop();
}
}
주요 특징 및 규칙
- 인터페이스는 인스턴스화할 수 없다.
- 인터페이스의 모든 메서드는
public이며, 추상 메서드는 별도의abstract키워드가 없어도 자동으로 추상 메서드로 간주된다. - 일반 클래스가 인터페이스를 구현하면 해당 인터페이스의 모든 메서드를 구현해야 한다.
- 추상 클래스는 인터페이스를 구현하지 않아도 된다.
추가 예제: 추상 클래스와 인터페이스의 차이점 설명
package com.example.interface_;
public class InterfaceDetail {
public static void main(String[] args) {
// IA 인터페이스는 인스턴스화할 수 없음
// new IA(); // 컴파일 에러 발생
}
}
// 인터페이스 정의
interface IA {
void say();
void hi();
}
// IA 인터페이스를 구현한 클래스
class Cat implements IA {
@Override
public void say() {
System.out.println("고양이는 울어요!");
}
@Override
public void hi() {
System.out.println("안녕하세요!");
}
}
// 추상 클래스는 인터페이스의 메서드를 선택적으로 구현 가능
abstract class Tiger implements IA {}
인터페이스 속성 및 확장
- 하나의 클래스는 여러 인터페이스를 동시에 구현할 수 있다.
- 인터페이스의 속성은 항상
public static final이다. - 인터페이스는 다른 클래스를 상속할 수 없지만, 여러 인터페이스를 확장할 수 있다.
- 인터페이스의 접근 제한자는
public또는 기본 접근 제한자만 사용할 수 있다.
속성 및 확장 관련 코드
package com.example.interface_;
public class InterfaceProperties {
public static void main(String[] args) {
System.out.println(IB.CONSTANT); // 인터페이스의 상수 접근 방법
}
}
interface IB {
int CONSTANT = 10; // 자동으로 public static final 처리됨
void hello();
}
interface IC {
void bye();
}
// 다중 인터페이스 확장
interface ID extends IB, IC {}
// 기본 접근 제한자 사용
interface IE {}
// 다중 인터페이스 구현
class Pig implements IB, IC {
@Override
public void hello() {
System.out.println("돼지는 인사합니다!");
}
@Override
public void bye() {
System.out.println("돼지는 작별 인사합니다!");
}
}
인터페이스 vs 상속
인터페이스와 상속은 서로 다른 문제를 해결하기 위해 존재한다.
- 상속: 부모 클래스로부터 기능을 재사용하고 유지보수성을 높임.
- 인터페이스: 다양한 클래스들이 공통된 규격(메서드)을 따르도록 설계함.
예제: 상속과 인터페이스의 조합
package com.example.interface_;
public class InheritanceVsInterface {
public static void main(String[] args) {
LittleMonkey wuKong = new LittleMonkey("손오공");
wuKong.climb();
wuKong.swim();
wuKong.fly();
}
}
// 기본 클래스
class Monkey {
private String name;
public Monkey(String name) {
this.name = name;
}
public void climb() {
System.out.println(name + "은 나무를 타요.");
}
}
// 인터페이스
interface Swimmable {
void swim();
}
interface Flyable {
void fly();
}
// 상속과 인터페이스 조합
class LittleMonkey extends Monkey implements Swimmable, Flyable {
public LittleMonkey(String name) {
super(name);
}
@Override
public void swim() {
System.out.println(getName() + "은 물고기처럼 수영합니다.");
}
@Override
public void fly() {
System.out.println(getName() + "은 새처럼 날아다닙니다.");
}
}
다형성
인터페이스는 다형성을 지원하며, 이를 통해 유연한 코드 설계가 가능하다.
예제: 다형성 배열
package com.example.interface_;
public class PolymorphismArray {
public static void main(String[] args) {
Usb[] devices = new Usb[2];
devices[0] = new MobilePhone();
devices[1] = new Camera();
for (Usb device : devices) {
device.start();
if (device instanceof MobilePhone) {
((MobilePhone) device).call();
}
}
}
}
interface Usb {
void start();
}
class MobilePhone implements Usb {
@Override
public void start() {
System.out.println("휴대폰 시작...");
}
public void call() {
System.out.println("전화 걸기...");
}
}
class Camera implements Usb {
@Override
public void start() {
System.out.println("카메라 시작...");
}
}