php 입문 | 구조와 객체 지향 | 상속에 의한 기능 확장


객체 지향에는 작성한 클래스는 여러 곳에서 재사용할 수 있다. 하지만 실제로 사용하려고 하면 “여기를 이렇게 재작업하여 사용하고 싶다"라든지 “이것은 기능으로 좀 부족 하니까 더 확장하고 싶다"는 것도 나올 것이다.

이런 경우에 클래스의 코드를 재작성하여 변경하는 것도 하나의 방법이지만, 만약 큰 프로젝트에서 많은 곳에 이미 사용되고 있거나 했을 때, 마음대로 클래스의 내용을 변경해서는 안될 것이다. 그렇다고 해서 클래스의 코드를 복사하고 또한 새로운 클래스를 만드는 것은 바보 같은 짓이다. 거의 같고 일부만 조금 다른 클래스를 여러 만드는 것은 코드의 낭비이다.

아래의 클래스는 건드리지 않고, 최소한의 수정만으로 클래스를 재사용 할 수 있게 한다는 생각을 바탕으로 만들어진 것이 ‘상속’이라는 개념이다.

상속은 이미있는 클래스의 기능을 그대로 모두 계승하고 새로운 클래스를 만드는 것이다. 이것은 다음과 같이 클래스를 정의하여 사용할 수 있다.

class 클래스명 extends 상속하는 클래스 {...}

이 상속하는 근원이 되는 클래스를 “슈퍼 클래스”, 상속하고 새로 만든 클래스를 “서브 클래스"라고 한다. 서브 클래스는 슈퍼 클래스의 모든 필드, 메소드를 이어 받아 그대로 사용할 수 있다 (그러나, 액세스 키워드가 private으로 된 것은 감춰져 있기 때문에 사용할 수 없다).

아래는 이전에 예제를 더 수정 한 것이다.

<?php
class TextModify {
    private $header = "<b>";
    private $footer = "</b>";
    private $body = "";
    private $find = "PHP";
     
    public function __construct($h,$f){
        $this->setHeader($h);
        $this->setFooter($f);
    }
     
    function setHeader($s){
        $this->header = $s;
    }
     
    function setFooter($s){
        $this->footer = $s;
    }
     
    function setBody($s){
        $this->body = htmlspecialchars(strtoupper($s));
    }
    function setFind($s){
        $this->find = $s;
    }
     
    function getRenderText(){
            $res = str_replace($this->find, $this->header . $this->find . $this->footer, $this->body);
        return $res;
    }
     
    function writeRenderText(){
        echo $this->getRenderText();
    }
}
 
class TitleModify extends TextModify {
     
    public function __construct($s){
        $this->setHeader('<span style="color:red;">');
        $this->setFooter('</span>');
        $this->setFind('PHP');
        $this->setBody($s);
    }
}
 
class MsgModify extends TextModify {
     
    public function __construct($s){
        $this->setHeader('<span style="color:blue;">');
        $this->setFooter('</span>');
        $this->setFind('PHP');
        $this->setBody($s);
    }
}
 
class RepModify extends TextModify {
     
    public function __construct($s){
        $this->setHeader('<b>');
        $this->setFooter('</b>');
        $this->setFind('PHP');
        $this->setBody($s);
    }
}
 
// 인스턴스 준비
$title_obj = new TitleModify('Hello PHP!');
$msg_obj = new MsgModify('여기에 PHP라는 문자를 포함한 문장을 써주세요.');
if ($_POST != null){
    $str = $_POST['text1'];
    $rep_obj = new RepModify($str);
}
?>
<!DOCTYPE html>
<html lang="ko">
    <head> 
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
        <title>sample page</title>
    </head>
    <body>
        <h1><?php $title_obj->writeRenderText(); ?></h1>
        <p><?php $msg_obj->writeRenderText(); ?></p>
        <hr>
        <p><?php if (isset($rep_obj)) $rep_obj->writeRenderText(); ?></p>
        <form method="post" action="./index.php">
            <textarea name="text1" cols="40" rows="5"><?php echo $str; ?></textarea>
            <br><input type="submit">
        </form>
        <hr>
    </body>
</html>

여기에서는 TextModify 클래스를 상속하여 “TitleModify”, “MsgModify”, “RepModify"라는 서브 클래스를 만들었다. 각 클래스에서는 각각 __construct을 준비하여 필요한 설정을 할 수 있도록 하고 있다.

이 서브 클래스들에는 생성자 밖에 없지만, 그 안에 각 필드의 값을 접근 메소드로 설정하고 있으며, 실제 이용은 writeRenderText로 출력을 하고 있다. 슈퍼 클래스 TextModify의 기능을 그대로 사용할 수 있다는 것을 알 수 있다.

이렇게하여 클래스를 상속해서 기능을 더 확장하여 재사용하는 것으로, 보다 유연하게 클래스 작성을 할 수 있게 되는 것이다.