[JAVA_개념 복습] implements, 인터페이스, 구현체

dejeong·2024년 10월 23일
0

JAVA

목록 보기
23/24
post-thumbnail

인터페이스 (Interface) 와 implements

  • 인터페이스 : 클래스들이 구현해야 할 메소드들을 정의해 놓은 틀이다. 인터페이스는 구현하지 않고 “이런 메소드들이 있어야 한다” 라고 명시하는 것에 가깝다. 이 인터페이스를 구현하는 클래스는 그 메소드를 반드시 작성해야 한다.
  • 인터페이스는 다중 상속을 가능하게 하고, 클래스가 특정 기능을 반드시 구현하도록 강제한다.
public interface Animal {
    void makeSound();  // 소리를 내는 메소드
}
  • implements : 클래스가 특정 인터페이스를 “구현”할 때 사용한다. 이를 통해 클래스는 해당 인터페이스가 요구하는 메소드를 반드시 구현해야 한다.
public class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Bark");
    }
}

Dog 클래스는 Animal 인터페이스를 구현(implements)하고, makeSound() 메소드를 정의해야 한다.


인터페이스와 메소드의 관계

  • 인터페이스 : 인터페이스는 메소드의 시그니처(이름, 반환형, 매개변수)만 정의하고, 그 메소드의 구체적인 동작은 구현하지 않습니다.
  • 메소드 : 인터페이스에 선언된 대로 실제로 구현한 코드이다. 이를 통해 인터페이스가 정한 틀을 따르면서도 각 클래스가 자신의 방식으로 기능을 구현할 수 있다.
// 인터페이스 정의
public interface Vehicle {
    void start(); // 시동을 걸다
    void stop();  // 멈추다
}
// Car 클래스가 Vehicle 인터페이스 구현
public class Car implements Vehicle {
    @Override
    public void start() {
        System.out.println("Car is starting");
    }

    @Override
    public void stop() {
        System.out.println("Car is stopping");
    }
}
// Bicycle 클래스도 Vehicle 인터페이스 구현
public class Bicycle implements Vehicle {
    @Override
    public void start() {
        System.out.println("Bicycle is starting");
    }

    @Override
    public void stop() {
        System.out.println("Bicycle is stopping");
    }
}

Vehicle 인터페이스는 start()stop() 메소드를 정의하지만, 구체적인 동작은 각각 CarBicycle 클래스에서 다르게 구현된다.

인터페이스를 사용하는 이유

  1. 표준화: 인터페이스는 모든 클래스가 동일한 메소드 시그니처를 가지도록 강제한다. 예를 들어, Vehicle 인터페이스를 구현하는 모든 클래스는 반드시 start()stop() 메소드를 구현해야 하므로 일관성을 유지할 수 있다.
  2. 다형성: 인터페이스는 다형성을 지원한다. 하나의 인터페이스를 구현한 여러 클래스를 하나의 타입으로 다룰 수 있다. 예를 들어, Vehicle 인터페이스를 구현한 CarBicycle 객체를 동일한 Vehicle 타입으로 처리할 수 있다.
/*
	* 다형성 예시
*/
public class Main {
    public static void main(String[] args) {
        Vehicle car = new Car();
        Vehicle bike = new Bicycle();

        car.start();  // Car is starting
        bike.start(); // Bicycle is starting
    }
}
  1. 유연한 설계 : 인터페이스를 사용하면 클래스 간 결합도를 낮출 수 있다. 구현체가 변경되더라도 인터페이스를 통해 프로그램을 유지보수할 수 있기 때문에 변경에 유연하다.
  2. 다중 상속 : 자바에서는 클래스의 다중 상속이 불가능하지만, 인터페이스는 여러 개를 구현할 수 있다. 이는 클래스가 여러 인터페이스를 구현하여 다양한 동작을 가질 수 있게 한다.

[다중 인터페이스 구현 예시]

/*
 * Flyable 인터페이스 정의
 */
public interface Flyable {
    void fly(); // 비행 메소드
}
/*
 * Swimable 인터페이스 정의
 */
public interface Swimable {
    void swim(); // 수영 메소드
}
/*
 * Duck 클래스가 Flyable과 Swimable 인터페이스를 구현
 */
public class Duck implements Flyable, Swimable {
    @Override
    public void fly() {
        System.out.println("The duck is flying");
    }

    @Override
    public void swim() {
        System.out.println("The duck is swimming");
    }
}

인터페이스는 주로 어떨 때 작성하는가?

  1. 다양한 구현체를 만들 때: 인터페이스를 사용하면 동일한 메소드 이름을 가진 다양한 구현체를 만들 수 있다. 예를 들어, 다양한 종류의 Vehicle 클래스(자동차, 자전거 등)를 만들고 싶을 때, Vehicle 인터페이스를 정의할 수 있습니다.
  2. 표준을 정할 때: 여러 클래스가 동일한 메소드를 가져야 하는 경우에 인터페이스를 사용하여 메소드 규격을 표준화한다.
  3. 프로젝트 구조를 명확하게 설계할 때: 인터페이스를 사용하면 큰 프로젝트에서 각 구성 요소의 책임과 역할을 명확하게 정의할 수 있다.
  4. 다형성(polymorphism)을 사용할 때: 다양한 클래스가 동일한 인터페이스를 구현하고, 이를 통해 객체들을 동일한 방식으로 다룰 때 사용된다. 다형성은 유지보수성과 확장성에 큰 도움이 된다.

인터페이스와 구현체

  • 구현체 : 인터페이스 또는 추상 클래스에 정의된 메소드의 실제 동작을 구현한 클래스를 말한다.

인터페이스는 클래스가 따라야 할 설계도 역할을 한다. 하지만 인터페이스 자체에는 메소드의 구체적인 동작이 정의되어 있지 않고, 그저 메소드의 이름시그니처(입력과 출력)만 정의되어 있습니다. 이 인터페이스를 따르는 실제 클래스가 이 메소드들의 구체적인 동작을 구현하게 되는데, 그 구현한 클래스구현체라고 부릅니다.

구현체의 예시

/*
	인터페이스 정의
*/
public interface Animal {
    void makeSound(); // 메소드 시그니처만 정의 (구현 X)
}
/*
	구현체 클래스
*/
public class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Bark");
    }
}

public class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow");
    }
}
  • Animal은 인터페이스로, makeSound()라는 메소드를 정의했지만, 구현되지 않음.
  • DogCat 클래스는 구현체로, makeSound() 메소드의 구체적인 동작을 각각 다르게 구현
  • 즉, Dog는 "Bark" 소리를 내고, Cat은 "Meow" 소리를 내는 방식으로 메소드를 구현

구현체를 사용하는 이유

  1. 유연성과 확장성: 여러 클래스가 동일한 인터페이스를 구현함으로써, 다양한 동작을 가진 객체들을 동일한 방식으로 사용할 수 있다. 예를 들어, Animal 인터페이스를 사용하는 코드는 Dog, Cat과 같은 다양한 구현체와 상호작용할 수 있다.
  2. 다형성: 구현체를 통해 다형성(polymorphism)을 실현할 수 있다. 예를 들어, 인터페이스 타입의 변수를 선언하고, 그 변수가 다양한 구현체의 인스턴스를 참조할 수 있다.
Animal myAnimal = new Dog(); // Dog 객체를 참조
myAnimal.makeSound(); // "Bark" 출력

myAnimal = new Cat(); // Cat 객체를 참조
myAnimal.makeSound(); // "Meow" 출력
  1. 결합도 낮추기: 인터페이스를 통해 코드의 결합도를 낮출 수 있어 유지보수와 테스트가 더 쉬워진다. 구체적인 구현에 의존하지 않고 인터페이스에 의존하면, 나중에 구현체가 바뀌어도 인터페이스에 맞추기만 하면 된다.

[인터페이스, 메소드, 그리고 객체 선언과 관련된 코드 예제]

/*
 * Vehicle 인터페이스 정의
 */
public interface Vehicle {
    // 메소드: 시동을 걸다
    void start(); 
    
    // 메소드: 멈추다
    void stop();  
}
/*
 * Vehicle 인터페이스를 구현하는 Car 클래스
 */
public class Car implements Vehicle {
    // 필드: 자동차의 색상
    private String color;

    // 생성자: Car 객체 생성 시 색상을 설정
    public Car(String color) {
        this.color = color;
    }

    // 메소드: 자동차가 시작할 때 호출됨
    @Override
    public void start() {
        System.out.println(color + " Car is starting"); // 자동차 시작 메소드
    }

    // 메소드: 자동차가 멈출 때 호출됨
    @Override
    public void stop() {
        System.out.println(color + " Car is stopping"); // 자동차 정지 메소드
    }
}
/*
 * Vehicle 인터페이스를 구현하는 Bicycle 클래스
 */
public class Bicycle implements Vehicle {
    // 필드: 자전거의 종류
    private String type;

    // 생성자: Bicycle 객체 생성 시 종류를 설정
    public Bicycle(String type) {
        this.type = type;
    }

    // 메소드: 자전거가 시작할 때 호출됨
    @Override
    public void start() {
        System.out.println(type + " Bicycle is starting"); // 자전거 시작 메소드
    }

    // 메소드: 자전거가 멈출 때 호출됨
    @Override
    public void stop() {
        System.out.println(type + " Bicycle is stopping"); // 자전거 정지 메소드
    }
}
/*
 * 메인 클래스에서 Vehicle 인터페이스를 사용하는 예제
 */
public class Main {
    public static void main(String[] args) {
        // Vehicle 타입의 참조 변수 선언
        Vehicle myCar = new Car("Red"); // Car 객체 생성 (색상: Red)
        Vehicle myBicycle = new Bicycle("Mountain"); // Bicycle 객체 생성 (종류: Mountain)

        // Car 객체의 메소드 호출
        myCar.start(); // "Red Car is starting" 출력
        myCar.stop();  // "Red Car is stopping" 출력

        // Bicycle 객체의 메소드 호출
        myBicycle.start(); // "Mountain Bicycle is starting" 출력
        myBicycle.stop();  // "Mountain Bicycle is stopping" 출력
    }
}

🤚 Vehicle 타입의 참조 변수? Vehicle 인터페이스를 기반으로 한 변수

Vehicle 타입의 참조 변수는Vehicle 인터페이스를 구현한 클래스의 객체를 참조할 수 있는 변수를 의미한다. 자바에서 인터페이스는 객체가 따라야 하는 계약(규칙)을 정의하며, 이 인터페이스를 구현한 클래스의 객체를 참조할 수 있는 타입을 제공한다.

  • Vehicle myCar;와 같은 선언은 myCar라는 변수가 Vehicle 타입임을 나타낸다.
  • 이 변수는 Vehicle 인터페이스를 구현한 어떤 객체도 참조할 수 있다. 예를 들어, Car 또는 Bicycle 객체를 참조할 수 있다.

장점으로는 다형성을 활용하여 여러 객체를 동일한 방식으로 다룰 수 있으며, 코드의 유연성과 일관성을 유지할 수 있다.

profile
룰루

0개의 댓글