Menu
Coddy logo textTech

인터페이스와 추상 클래스 비교

Coddy PHP 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 91개 중 30번째.

이제 interfaceabstract 클래스를 모두 배웠으니, 각각을 언제 사용해야 하는지 명확히 알아보겠습니다. 둘은 비슷해 보일 수 있지만 서로 다른 목적과 고유한 기능을 제공합니다.

기능 인터페이스 추상 클래스
메서드 메서드 시그니처만 추상 메서드와 구체 메서드 모두
속성 상수만 속성을 가질 수 있음
다중 상속 class는 여러 개를 구현할 수 있음 class는 하나만 상속할 수 있음
생성자 __construct 시그니처를 선언할 수 있음(본문 없음) 본문이 있는 constructor를 정의할 수 있음

서로 관련이 없는 클래스들이 충족할 수 있는 계약을 정의하려면 interface를 사용하세요. 예를 들어 PrinterLogger는 공통 조상을 공유하지 않더라도 둘 다 Writable interface를 구현할 수 있습니다.

공통 코드를 공유하는 관련된 class들이 있을 때 abstract class를 사용하세요. DogCat class에 동일한 eat() method 구현이 모두 필요한 경우, abstract Animal class를 사용하면 해당 코드를 한 번만 작성할 수 있습니다.

두 접근 방식을 결합할 수도 있습니다. 클래스는 여러 인터페이스를 Implement하면서 abstract 클래스를 extends할 수 있습니다.

<?php
abstract class Animal {
    protected $name;
    
    public function eat() {
        return $this->name . " is eating";
    }
}

interface Swimmable {
    public function swim();
}

class Duck extends Animal implements Swimmable {
    public function __construct($name) {
        $this->name = $name;
    }
    
    public function swim() {
        return $this->name . " is swimming";
    }
}

핵심 요점: 서로 관련 없는 클래스 전반에서 기능을 정의하려면 interface를 선택하세요. 관련된 클래스 간에 코드를 공유해야 할 때는 abstract 클래스를 선택하세요.

challenge icon

챌린지

쉬움

추상 클래스와 인터페이스를 언제 사용해야 하는지, 그리고 두 접근 방식을 어떻게 효과적으로 결합할 수 있는지 보여 주는 차량 시스템을 만들어 봅시다.

상속을 통해 차량이 공통 속성을 공유하면서도 인터페이스를 통해 추가 기능을 얻을 수 있는 시스템을 만들게 됩니다. 이는 실제 설계 결정을 반영합니다. 자동차는 차량이라는 "is a" 관계를 가지지만, 동시에 연료를 보급할 수 있는 "has the capability"도 가집니다.

코드를 네 개의 파일로 구성하세요.

  • Refuelable.php: 단일 메서드 시그니처인 refuel($amount)를 포함하는 Refuelable interface를 Define하세요. 이 기능은 상속 계층과 관계없이 연료 보급이 필요한 모든 class에 적용될 수 있습니다.
  • Vehicle.php: 모든 차량에 공유 기능을 제공하는 abstract Vehicle class를 Define하세요. protected $brand property와 protected $fuelLevel property(0에서 시작)를 가져야 합니다. constructor는 브랜드 이름을 accepts합니다. 브랜드를 반환하는 구체적인 getBrand() method, 현재 연료 level을 반환하는 구체적인 getFuelLevel() method, 그리고 자식 class가 Implement해야 하는 abstract drive() method를 포함하세요.
  • Car.php: Vehicle을 extends하고 Refuelable을 implements하는 Car class를 Create하세요. 두 필수 파일을 맨 위에서 include하세요. constructor는 브랜드를 accepts하고 이를 parent constructor에 passes합니다. drive()를 Implement하여 "[brand] car is driving"을 반환하세요. refuel($amount)를 Implement하여 amount를 fuel level에 Add하고 "[brand] refueled to [fuelLevel] liters"를 반환하세요.
  • main.php: Car 파일을 include하세요. 두 개의 입력, 즉 브랜드 이름과 fuel amount를 받습니다(정수로 변환). 브랜드를 사용해 Car를 Create하세요. 첫 번째 line에는 drive()의 결과를 Print하고, 두 번째 line에는 fuel amount와 함께 refuel()의 결과를 Print하세요.

이 challenge는 핵심적인 차이를 보여 줍니다. abstract Vehicle class는 코드를 공유하고 "is-a" 관계를 설정하는 반면, Refuelable interface는 generator나 boat처럼 서로 관련이 없는 다른 class에도 적용될 수 있는 capability를 추가하며, 해당 class가 차량일 것을 요구하지 않습니다.

직접 해보기

<?php
require_once 'Car.php';

// 입력 읽기
$brand = trim(fgets(STDIN));
$fuelAmount = intval(trim(fgets(STDIN)));

// TODO: 브랜드로 Car 생성

// TODO: 첫 번째 줄에 drive()의 결과 출력

// TODO: 두 번째 줄에 연료량으로 refuel()의 결과 출력
?>
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 PHP 컴파일러