오늘도 조금 쉬운 개념으로 돌아왔다
자바의 인터페이스는 메서드 선언의 집합만을 포함하며, 구현이 없는 추상적인 형식을 정의한다.
클래스가 인터페이스를 구현하면, 해당 인터페이스의 모든 메서드를 반드시 구현해야 한다. 이 부분은 뒤에서 다시 설명하겠다.
인터페이스는 코드의 유연성과 확장성을 높이며, 다중 상속을 지원하지 않는 자바에서 다른 클래스와 기능을 공유하는 중요한 방법이다.
자바의 인터페이스는 일종의 계약서나 청사진으로 비유할 수 있다.
이 비유를 통해서 인터페이스의 개념과 역할을 쉽게 이해해보자.
계약서로 비유를 들어보았다.
생각해보자. 나는 한 건설 회사의 사장이다. 나는 여러 다른 하청업체와 계약을 맺고 건물을 짓고 싶다.
각 하청업체는 건물의 특정 부분을 담당해야 한다. 전기, 배관, 인테리어 등등 여러 부분을 신경 써야 한다.
나는 사장이기 때문에 각 하청업체가 반드시 따라야 할 표준을 명확히 정의한 계약서를 작성해야 한다.
이 계약서엔 각 업체가 제공해야 할 서비스가 명시되어 있다. 하지만 계약서엔 각 서비스가 어떻게 수행되어야 하는지에 대한 구체적인 내용은 포함되어 있지 않다.
1. 인터페이스 선언은 계약서 작성과 같다:
인터페이스는 특정 클래스가 반드시 구현해야 하는 메서드들을 정의한다. 건설 회사가 하청업체에 제공해야 할 서비스 목록을 계약서에 명시하는 것과 같다.
public interface BuildingService {
void installElectricity(); //전기 회사
void installPlumbing(); // 배관 회사
void doInterior(); //인테리어 회사
}
이런 식으로 먼저 서비스 목록을 계약서에 명시하는 것이다.
2. 클래스가 인터페이스를 구현하는 것은 계약을 이행하는 것과 같다.
각 하청업체는 계약서에 명시된 서비스를 제공해야 한다.
마찬가지로, Java 클래스가 인터페이스를 구현하면, 해당 인터페이스에 정의된 모든 메서드를 구현해야 한다.
public class ElectricalCompany implements BuildingService {
@Override
public void installElectricity() {
System.out.println("Installing electricity...");
}
@Override
public void installPlumbing() {
// 전기 회사는 배관을 설치하지 않으므로 이 메서드는 빈 채로 둔다.
}
@Override
public void doInterior() {
// 전기 회사는 인테리어를 하지 않으므로 이 메서드는 빈 채로 둔다.
}
}
public class PlumbingCompany implements BuildingService {
@Override
public void installElectricity() {
// 배관 회사는 전기를 설치하지 않으므로 이 메서드는 빈 채로 둔다.
}
@Override
public void installPlumbing() {
System.out.println("Installing plumbing...");
}
@Override
public void doInterior() {
// 배관 회사는 인테리어를 하지 않으므로 이 메서드는 빈 채로 둔다.
}
}
public class InteriorCompany implements BuildingService {
@Override
public void installElectricity() {
// 인테리어 회사는 전기를 설치하지 않으므로 이 메서드는 빈 채로 둔다.
}
@Override
public void installPlumbing() {
// 인테리어 회사는 배관을 설치하지 않으므로 이 메서드는 빈 채로 둔다.
}
@Override
public void doInterior() {
System.out.println("Doing interior work...");
}
}
굳이 왜 사용하지도 않는 메서드를 각각의 클래스에 추가해야 하는지 헷갈릴 수도 있다.
그러나 하나의 인터페이스에 모든 메서드를 정의하면 이를 구현하는 클래스는 인터페이스에 정의된 모든 메서드를 구현해야 한다.
이는 클래스가 실제로 사용하지 않는 메서드도 포함되기 때문인데, 각각의 인터페이스를 따로따로 나눠서 설계하는 방법도 있다.
public interface ElectricalService {
void installElectricity();
}
public interface PlumbingService {
void installPlumbing();
}
public interface InteriorService {
void doInterior();
}
이런 식으로 인터페이스를 작성하는 방법도 있으나 복잡하지 않은 간단한 코드이므로 그냥 하나의 인터페이스 안에서 사용하는 것으로 하겠다.
3. 다형성
나는 계약서(인터페이스)를 기반으로 여러 하청업체(클래스)를 고용할 수 있다.
계약서가 어떤 특정한 구현에 구애받지 않기 때문에, 언제든 다른 하청업체로 교환할 수도 있다.
건설 프로젝트 관리를 위한 ConstructionManager 클래스를 생성해보겠다.
public class ConstructionManager {
private BuildingService service;
public void setService(BuildingService service) {
this.service = service;
}
public void startWork() {
service.installElectricity();
service.installPlumbing();
service.doInterior();
}
}
이렇게 ConstructionManager 클래스는 건설 프로젝트를 관리하고 조정하는 역할을 한다. 이 클래스는 다양한 서비스(전기, 배관, 인테리어 등)를 설정하고, 각 서비스에 대해 작업을 시작할 수 있도록 한다.
main에서 작업을 수행해보겠다.
public class Main {
public static void main(String[] args) {
ConstructionManager manager = new ConstructionManager();
BuildingService electricalService = new ElectricalCompany();
BuildingService plumbingService = new PlumbingCompany();
BuildingService interiorService = new InteriorCompany();
manager.setService(electricalService);
manager.startWork();
manager.setService(plumbingService);
manager.startWork();
manager.setService(interiorService);
manager.startWork();
}
main에서 같은 startWork지만 다른 역할을 하는 다형성 기능을 수행하여 다음과 같은 결과를 얻을 수 있었다.
간단한 비유를 통한 인터페이스에 대해 공부해보았다.
'Language > Java' 카테고리의 다른 글
[Java] 다형성의 본질과 활용 (1) | 2024.12.31 |
---|---|
[Java] String / StringBuffer / StringBuilder 차이점 (0) | 2024.10.04 |
[Java] 멤버 변수 초기화에 관하여 (52) | 2024.06.21 |
[Java] 형변환, 조건문, 반복문 (46) | 2024.06.14 |
[Java] 자바 설명, 자료형, 변수, 상수 개념 및 사용 (2) | 2024.04.28 |