abstract 키워드를 사용하여 선언합니다.
직접 new로 인스턴스화할 수 없습니다.
추상 메서드(구현이 없는 메서드)와 구체 메서드(일반 메서드)를 혼합할 수 있습니다.
상속받는 자식 클래스는 추상 메서드를 반드시 구현해야 합니다.
abstract class Animal {
// 추상 메서드 (자식이 반드시 구현해야 함)
abstract public function makeSound(): void;
// 구체 메서드 (공통 동작 제공)
public function eat(): void {
echo "먹는 중...\n";
}
}
class Dog extends Animal {
public function makeSound(): void {
echo "멍멍\n";
}
}
class Cat extends Animal {
public function makeSound(): void {
echo "야옹\n";
}
}
$dog = new Dog();
$dog->makeSound(); // 멍멍
$dog->eat(); // 먹는 중...
메서드의 시그니처(이름, 매개변수, 반환 타입)만 정의하고 본문은 없습니다.
자식 클래스가 반드시 구현(override) 해야 합니다.
접근 제어자는 public 또는 protected만 허용됩니다. (private은 불가능)
abstract public function process(string $data): bool;
상속 전용
추상 클래스는 단독으로 객체 생성 불가.
반드시 extends 해서 사용해야 합니다.
공통 로직 + 구현 강제
여러 자식 클래스가 공유해야 하는 코드를 추상 클래스에 넣을 수 있음.
동시에 추상 메서드로 “이 메서드는 꼭 구현해야 한다”는 계약을 강제.
다중 상속 불가
클래스는 하나의 추상 클래스만 상속받을 수 있습니다. (PHP는 다중 클래스 상속을 지원하지 않음)
대신 인터페이스 다중 구현 + 추상 클래스 상속 조합이 흔히 사용됩니다.
구분 |
Abstract class |
Interface |
---|---|---|
목적 |
기본 구조 + 강제 구현 |
계약(Contract)만 정의 |
메서드 |
추상 + 구체 혼합 가능 |
모든 메서드는 public, 구현 없음 |
프로퍼티 |
인스턴스 변수, 상태 보관 가능 |
불가 (PHP 8.1에서 제한적으로 readonly 프로퍼티 지원) |
상속/구현 |
클래스 단일 상속만 가능 |
여러 인터페이스 다중 구현 가능 |
공통 로직 |
가능 (메서드 구현, 멤버 변수 활용) |
불가능 |
abstract class Report {
// 템플릿 메서드: 실행 순서 정의
public function generate(): void {
$this->header();
$this->body();
$this->footer();
}
abstract protected function header(): void;
abstract protected function body(): void;
abstract protected function footer(): void;
}
class HtmlReport extends Report {
protected function header(): void { echo "<h1>HTML Header</h1>"; }
protected function body(): void { echo "<p>HTML Body</p>"; }
protected function footer(): void { echo "<footer>HTML Footer</footer>"; }
}
class TextReport extends Report {
protected function header(): void { echo "TEXT Header\n"; }
protected function body(): void { echo "TEXT Body\n"; }
protected function footer(): void { echo "TEXT Footer\n"; }
}
$r = new HtmlReport();
$r->generate();
Report 클래스는 전체 실행 흐름(generate) 을 제공하고,
세부 부분(header, body, footer)은 자식 클래스에 강제합니다.
예: 모든 Controller 클래스는 handle() 메서드를 반드시 가져야 함.
abstract class Controller {
abstract public function handle(Request $req, Response $res): void;
protected function render(string $view): void {
include $view;
}
}
공통 동작은 추상 클래스, 계약은 인터페이스
여러 클래스가 같은 동작을 공유해야 하면 abstract class
단순히 “이 메서드를 반드시 제공해야 한다”라면 interface
하나의 클래스 계층 구조를 설계할 때 사용
추상 클래스는 상속 계층의 루트 역할을 할 때 적합.
코드 중복 제거
자식 클래스에 반복되는 로직은 추상 클래스에서 제공.
abstract class는 인스턴스화 불가한 기본 설계도로, 공통 코드와 구현 강제 기능을 동시에 제공한다.
인터페이스보다 더 구체적인 기본 구현이 필요할 때 추상 클래스를 사용한다.
실무에서는 인터페이스(규약) + 추상 클래스(공통 로직) + 구현 클래스(세부 구현) 패턴으로 많이 활용된다.