PHP OOP에서 인터페이스 적용
이제 우리는 인터페이스가 클래스의 필요한 모든 메서드가 구현되었는지 통제하는 좋은 방법이라는 것을 알았습니다.
더 실용적인 또 다른 예를 살펴보겠습니다. 도형 객체 배열을 저장할 클래스가 있다고 가정합시다:
<?php
class FiguresCollection
{
private $figures = []; // 도형을 위한 배열
}
?>
컬렉션에 객체를 추가하기 위해 우리 클래스에
addFigure 메서드를 구현해 봅시다:
<?php
class FiguresCollection
{
private $figures = [];
// 매개변수로 도형 객체를 전달합니다:
public function addFigure($figure)
{
$this->figures[] = $figure;
}
}
?>
분명히, 우리는 addFigure 메서드의 매개변수로
도형 객체가 전달될 것이라고 기대하고 있습니다. 그러나
이에 대한 어떠한 통제도 없습니다!
타입 힌트를 사용하고 객체의 타입을 명시적으로
Figure로 지정해 봅시다:
<?php
class FiguresCollection
{
private $figures = [];
public function addFigure(Figure $figure)
{
$this->figures[] = $figure;
}
}
?>
우리가 무엇을 했는지 알아봅시다.
Figure가 실제로 존재하는 클래스였다면,
우리는 메서드의 매개변수로 해당 클래스의 객체와
그 자식 클래스의 객체를 전달할 수 있었을 것입니다.
그러나 우리의 경우, Figure는 인터페이스입니다.
이 경우, 힌트는 메서드 매개변수로 우리 인터페이스를
구현하는 클래스의 객체만 전달될 수 있음을 의미합니다.
우리 클래스의 객체를 생성하고 그 안에 도형들을 추가해 보겠습니다:
<?php
$figuresCollection = new FiguresCollection;
// 정사각형을 몇 개 추가합니다:
$figuresCollection->addFigure(new Quadrate(2));
$figuresCollection->addFigure(new Quadrate(3));
// 직사각형을 몇 개 추가합니다:
$figuresCollection->addFigure(new Rectangle(2, 3));
$figuresCollection->addFigure(new Rectangle(3, 4));
?>
다른 클래스의 객체를 추가하려는 시도는 오류를 발생시킵니다:
<?php
$figuresCollection = new FiguresCollection;
class Test {}; // 다른 클래스
$figuresCollection->addFigure(new Test); // 오류 발생
?>
이러한 통제가 실제로 우리에게 주는 이점:
컬렉션에 추가된 모든 도형이
Figure 인터페이스를 구현하므로,
우리는 각 도형이 getSquare 메서드와
getPerimeter 메서드를 가질 것임을
확신할 수 있습니다.
나중에 정사각형과 직사각형 외에도, 예를 들어
삼각형이 추가될 수 있습니다. 이 경우 삼각형도
마찬가지로 getSquare와
getPerimeter 메서드를 갖게 될 것입니다.
실제로 이것은 우리에게 다음과 같은 가능성을
제공합니다: 우리는 FiguresCollection
클래스에서, 예를 들어, 컬렉션 내 모든 도형의
전체 넓이를 구하는 getTotalSquare
메서드를 만들 수 있습니다. 이 메서드에서는
도형 배열을 루프로 순회하며 각 도형의
getSquare 메서드를 호출할 것입니다.
각 도형이 Figure 인터페이스를 구현하기 때문에,
우리는 각 도형이 이 getSquare 메서드를
100% 확신을 가지고 가질 것임을 알 수 있습니다.
자, 메서드 구현은 다음과 같습니다:
<?php
class FiguresCollection
{
private $figures = [];
public function addFigure(Figure $figure)
{
$this->figures[] = $figure;
}
// 전체 넓이를 구합니다:
public function getTotalSquare()
{
$sum = 0;
foreach ($this->figures as $figure) {
$sum += $figure->getSquare(); // getSquare 메서드 사용
}
return $sum;
}
}
?>
제 코드를 보지 않고 동일한
FiguresCollection 클래스를 구현해 보세요.
FiguresCollection 클래스에 모든 도형의
총 둘레를 구하는 getTotalPerimeter
메서드를 추가하세요.