Home > Backend > Java > ☕️[Java] 인터페이스

☕️[Java] 인터페이스
Java Programming Language Backend

1️⃣ 인터페이스.

1. 인터페이스(Interface).

자바에서 인터페이스(Interface)는 메서드의 시그니처만을 정의하는 참조 타입입니다.

인터페이스는 클래스가 구현(implement) 해야 하는 동작의 설계를 제공하며, 구현하는 모든 클래스에 대해 특정 메소드들이 반드시 존재하도록 강제합니다.

이는 다형성을 지원하는 강력한 방법으로, 서로 다른 클래스들이 동일한 인터페이스를 구현함으로써 동일한 방식으로 처리될 수 있게 해 줍니다.

1.2 인터페이스의 주요 특징.

  • 1. 메소드 선언만 포함 : 인터페이스는 메소드의 구현을 포함하지 않습니다.(자바 8 이전까지는).
    • 메소드의 몸체는 인터페이스를 구현하는 클래스에서 제공됩니다.
  • 2. 상수만 포함 가능 : 인터페이스는 상수만을 멤버로 가질수 있습니다.
    • 모든 필드는 ‘public’, ‘static’, ‘final’ 로 선언됩니다.
  • 3. 다중 구현 지원 : 한 클래스는 여러 인터페이스를 구현할 수 있으며, 이를 통해 다중 상속의 이점을 얻을 수 있습니다.

  • 4. 디폴트 메소드와 정적 메소드 : 자바 8 이후부터는 인터페이스에 디폴트 메소드(구현을 포함하는 메소드)와 정적 메소드를 정의할 수 있게 되었습니다.
    • 이를 통해 더 유연한 설계가 가능해졌습니다.

1.3 인터페이스 정의 예시.

public interface Vehicle {
    void start();
    void stop();
}
  • 위 예제에서 ‘Vehicle’ 인터페이스는 ‘start’‘stop’ 이라는 두 메소드를 정의합니다.
    • 이 인터페이스를 구현하는 모든 클래스는 이 두 메소드의 구체적인 구현을 제공해야 합니다.

1.4 인터페이스 구현 예.

public class Car implements Vehicle {
    @Override
    public void start() {
        System.out.println("Car starts.");
    }
    
    @Override
    public void stop() {
        System.out.println("Car stops.");
    }
}
  • ‘Car’ 클래스는 ‘Vehicle’ 인터페이스를 구현합니다.
    • 이 클래스는 start‘stop’ 메소드를 구체적으로 구현해야 합니다.

1.5 결론.

인터페이스는 클래스와 다른 클래스 사이의 계약을 정의하고, 특정 작업을 수행하는 메소드의 시그니처를 강제합니다.
이는 코드의 상호 운용성을 높이고, 다형성을 통한 유연한 프로그래밍 설계를 가능하게 합니다.
인터페이스를 사용함으로써 다양한 구현체를 동일한 방식으로 처리할 수 있어, 코드의 유지보수성과 확장성이 향상됩니다.


2. 상수(constant).

자바 프로그래밍에서 상수(constant)는 값이 선언 후 변경될 수 없는 변수를 의미합니다.

상수는 일반적으로 프로그램 전체에서 변하지 않는 값에 사용되며, 이는 코드의 읽기 쉬움과 유지 관리를 돕습니다.

자바에서 상수를 선언하기 위해 ‘final’ 키워드를 변수 선언과 함께 사용합니다.

2.1 상수의 특징.

  • 1. 불변성 : 상수는 한 번 초기화되면 그 값이 변경될 수 없습니다.
  • 2. 명확성 : 코드 내에서 직접적인 값보다는 의미 있는 이름을 가진 상수를 사용함으로써 코드의 가독성과 유지보수성이 향상됩니다.
  • 3. 공용 사용 : 자주 사용되는 값이나 의미가 명확한 수치를 상수로 선언하여 코드 전바에 걸쳐 재사용할 수 있습니다.

2.2 상수 선언 예시.

상수를 선언하는 방법은 간단합니다.
‘final’ 키워드를 사용하여 변수를 선언하고, 초기화합니다.
일반적으로 상수의 이름은 대문자로 표기하며, 단어 간에는 언더스코어(‘_‘)를 사용합니다.
이는 상수임을 쉽게 식별할 수 있도록 도와줍니다.

public class Constants {
    public static final int MAX_WIDTH = 800;
    public static final int MAX_HEIGHT = 600;
    public static final String COMPANY_NAME = "MyCompany";
}
  • 위 예에서 ‘MAX_WIDTH’, ‘MAX_HEIGHT’, ‘COMPANY_NAME’ 은 모두 상수이며, 이들의 값은 선언된 후 변경될 수 없습니다.

2.3 상수 사용의 이점.

  • 오류 감소 : 값이 한 번 설정되면 변경되지 않기 때문에, 예상치 못한 곳에서 값이 변경되어 발생할 수 있는 버그를 줄일 수 있습니다.
  • 코드 재사용성 : 한 곳에서 값을 변경하면, 해당 상수를 사용하는 모든 위치에서 변경된 값이 적용됩니다. 이는 일관성 유지와 함께 코드 관리를 간소화합니다.
  • 컴파일 시간 최적화 : 상수 값은 컴파일 시간에 결정되므로, 런타임에 추가적인 계산 비용이 들지 않습니다.

2.4 결론.

상수는 프로그램 내에서 변하지 않는 값을 나타내며, 코드의 안정성과 유지보수성을 높이는 데 중요한 역할을 합니다.
자바에서는 ‘final’ 키워드를 사용하여 이러한 상수를 쉽게 생성할 수 있습니다.


3. 클래스의 상속과 인터페이스의 구현을 동시에 사용.

자바에서는 클래스의 상속과 인터페이스의 구현을 동시에 사용하여 “다중 상속“과 유사한 효과를 얻을 수 있습니다.

이는 자바의 설계에서 클래스는 단일 상속만을 허용하지만, 인터페이스는 다중으로 구현할 수 있게 함으로써 이루어집니다.

3.1 단일 상속과 다중 인터페이스 구현.

  • 단일 상속 : 자바에서 클래스는 단 하나의 상위 클래스만 상속받을 수 있습니다.
    • 이는 C++ 같은 언어에서 볼 수 있는 다중 상속의 복잡성과 관련된 문제(예: 다이아몬드 문제)를 피하기 위함입니다.
  • 다중 인터페이스 구현 : 한 클래스는 여러 인터페이스를 구현할 수 있습니다.
    • 이는 인터페이스가 구체적인 구현을 포함하지 않기 때문에(자바 8 이전까지, 자바 8 이후에는 디폴트 메소드를 통해 일부 구현을 포함할 수 있음), 클래스가 여러 인터페이스를 구현함으로써 다중 상속의 효과를 나타낼 수 있습니다.

3.2 예시.

  • 다음 예시에서 ‘Car’ 클래스는 ‘Vehicle’ 클래스를 상속받고, ‘Electric’‘Autonomous’ 두 인터페이스를 구현하고 있습니다.
    • 이를 통해 ‘Car’ 클래스는 ‘Vehicle’ 클래스의 속성과 메소드를 상속받으며, 동시에 두 인터페이스의 메소드를 구현해야 합니다.
class Vehicle {
    void drive() {
        System.out.println("This vehicle is driving.");
    }
}

interface Electric {
    void charge();
}

interface Autonomous {
    void navigate();
}

class Car extends Vehicle implements Electric, Autonomous {
    @Override
    public void charge() {
        System.out.println("The car is charging.");
    }
    
    @Override
    public void navigate() {
        System.out.println("The car is navigating autonomously.");
    }
}

public class Main {
    public static void main(String[] args) {
        Car myCar = new Car();
        myCar.drive();
        myCar.charge();
        myCar.navigate();
    }
}

3.4 결론.

자바에서는 한 클래스가 단일 상속을 통해 한 클래스의 기능을 상속받고, 동시에 여러 인터페이스를 구현함으로써 다중 상속의 효과를 얻을 수 있습니다.
이는 자바의 타입 시스템이 제공하는 유연성을 활용하는 좋은 예시로, 소프트웨어 설계에서 필요한 다양한 기능을 조합할 수 있게 해 줍니다.