Java 인터페이스 마스터: 개념, 구현, 모범 사례
Java 인터페이스 완전 해설
Java 인터페이스는 구현 클래스가 준수해야 할 계약을 정의합니다. 추상화, 다중 상속을 가능하게 하고 깔끔하고 모듈화된 아키텍처를 촉진합니다.
인터페이스 정의
인터페이스는 완전히 추상적인 타입입니다. 모든 메서드는 암시적으로 public abstract, 모든 필드는 public static final입니다. interface 키워드로 선언:
interface Language { void getType(); void getVersion(); }
여기서 Language는 두 개의 추상 메서드를 가진 인터페이스입니다.
인터페이스 구현
인터페이스는 인스턴스화할 수 없습니다. 클래스는 implements 키워드로 구현하고 모든 추상 메서드에 구체적 본문을 제공합니다.
예제 1: Polygon 인터페이스
interface Polygon { void getArea(int length, int breadth); } class Rectangle implements Polygon { @Override public void getArea(int length, int breadth) { System.out.println("The area of the rectangle is " + (length * breadth)); } } class Main { public static void main(String[] args) { Rectangle r = new Rectangle(); r.getArea(5, 6); } }
출력:
The area of the rectangle is 30
예제 2: Language 인터페이스
interface Language { void getName(String name); } class ProgrammingLanguage implements Language { @Override public void getName(String name) { System.out.println("Programming Language: " + name); } } class Main { public static void main(String[] args) { ProgrammingLanguage lang = new ProgrammingLanguage(); lang.getName("Java"); } }
출력:
Programming Language: Java
여러 인터페이스 구현
클래스는 여러 인터페이스를 구현할 수 있습니다:
interface A { /* 멤버 */ } interface B { /* 멤버 */ } class C implements A, B { /* 구현 */ }
인터페이스 확장
인터페이스는 extends로 다른 인터페이스를 확장할 수 있습니다:
interface Line { /* 멤버 */ } interface Polygon extends Line { /* 멤버 */ }
Polygon을 구현하는 클래스는 Line과 Polygon 멤버 모두에 대한 메서드를 제공해야 합니다.
여러 인터페이스 확장
interface A { /* ... */ } interface B { /* ... */ } interface C extends A, B { /* ... */ }
왜 인터페이스를 사용하는가?
- 추상화: 구현을 강제하지 않고 연산 정의, 클래스별 다양한 동작 허용
- 명세: 구현 클래스가 이행해야 할 명확한 계약 설정
- 다중 상속: 클래스가 여러 소스에서 행동 채택 가능
- 기본 가시성: 모든 메서드 암시적
public, 필드는 public static final
암시적 상수 예:
interface Language { String TYPE = "programming language"; // 암시적 public static final void getName(); // 암시적 public }
Default 메서드 (Java 8+)
Java 8에서 default 메서드 도입으로 인터페이스에 구체적 메서드 본문 포함 가능:
default void getSides() { System.out.println("I can get sides of a polygon."); }
Default 메서드는 기존 구현을 깨지 않고 인터페이스에 새 메서드 추가 시 하위 호환성 제공.
예제: Default 메서드 사용
interface Polygon { void getArea(); default void getSides() { System.out.println("I can get sides of a polygon."); } } class Rectangle implements Polygon { @Override public void getArea() { int length = 6; int breadth = 5; int area = length * breadth; System.out.println("The area of the rectangle is " + area); } @Override public void getSides() { System.out.println("I have 4 sides."); } } class Square implements Polygon { @Override public void getArea() { int length = 5; int area = length * length; System.out.println("The area of the square is " + area); } } class Main { public static void main(String[] args) { Rectangle r = new Rectangle(); r.getArea(); r.getSides(); Square s = new Square(); s.getArea(); s.getSides(); } }
출력:
The area of the rectangle is 30 I have 4 sides. The area of the square is 25 I can get sides of a polygon.
Static 및 Private 메서드 (Java 9+)
인터페이스는 이제 static 메서드를 포함할 수 있으며 인터페이스 이름으로 호출 가능:
interface Polygon { static void helper() { /* ... */ } } Polygon.helper();
Private 메서드는 다른 인터페이스 메서드용 내부 유틸리티를 제공하여 캡슐화 보장.
실전 예제: 다각형 계산
import java.lang.Math; interface Polygon { void getArea(); default void getPerimeter(int... sides) { int perimeter = 0; for (int side : sides) perimeter += side; System.out.println("Perimeter: " + perimeter); } } class Triangle implements Polygon { private final int a, b, c; private double area; Triangle(int a, int b, int c) { this.a = a; this.b = b; this.c = c; } @Override public void getArea() { double s = (a + b + c) / 2.0; area = Math.sqrt(s * (s - a) * (s - b) * (s - c)); System.out.println("Area: " + area); } } class Main { public static void main(String[] args) { Triangle t = new Triangle(2, 3, 4); t.getArea(); t.getPerimeter(2, 3, 4); } }
출력:
Area: 2.9047375096555625 Perimeter: 9
이 예제에서 Polygon 인터페이스는 재사용 가능한 getPerimeter 메서드를 제공하고 각 도형은 자체 면적 계산을 구현합니다.