프로그래밍 언어/PHP

PHP: 상속 (생성자, 가시성, Final)

상속

상속PHP: 클래스에서 잠깐 살펴보았듯, 를 표현합니다. 예를 들어 동물이라는 최상위 클래스를 상속받은 사람, 강아지, 고양이 등이 있을 수 있습니다. 상속이라는 개념을 사용하면 확장에 유용하고 추상 클래스인터페이스를 함께 사용하면 다양한 서드파티 클래스들을 받아서 이를 처리할 수 있게됩니다. 상속이라는 개념은 객체지향에서 중요한 개념이며 반드시 알아야 하는 사항이기도 합니다. 이는 PHP 뿐만 아니라 자바나 C++ 등 다른 언어에서도 중요합니다.

extends

상속을 사용하는 법 자체와 extends 키워드는 PHP: 클래스에서 알아보았으니 조금은 다른 주제에 대해 이야기해보자면, 상속과 함께 사용할 수 있는 개념인 생성자, 가시성, Final 키워드에 대한 것입니다. 개별의 주제는 각각 조금씩 다르지만 상속이라는 개념에서 공통적으로 사용하기 때문에 해당 파트에 넣게 되었습니다.

상속으로 발생하는 효과

상속으로 발생할 수 있는 효과를 알아보자면 면저 this 가 가르키는 스코프의 변화부모 클래스 타입에 대한 자식 클래스의 인스턴스 할당입니다. 상속을 사용하면 기본적으로 자식 클래스의 인스턴스는 부모 클래스 타입에 할당될 수 있습니다. 이러한 특성이 라이브러리가 서드파티 클래스를 조금 더 유연하게 사용될 수 있도록 해줍니다.

this

this 는 기본적으로 현재 객체를 말합니다만, 이러한 this 를 통해 메서드를 호출하는 경우 자식 클래스에 재정의가 되어있다면 자식 클래스의 메서드를 가르키지만, 그렇지 않다면 부모 클래스의 메서드를 호출하게 됩니다. 상속의 기본적인 특징 중 하나입니다.

class A
{
    public function foo()
    {
        var_dump(__METHOD__);
    }
}
class C extends A
{
}

$c = new C();
$c->foo(); // -> A::foo

부모 클래스 타입에 자식 클래스의 인스턴스를 넘기기

제목 그대로 부모 클래스의 타입에 자식 클래스의 인스턴스를 넘길 수 있습니다. 이는 함수 및 메서드에서 사용하는 경우가 많으며 객체지향 프로그래밍을 한다면 필수적으로 활용해야 할 요소이며, 설계적 측면에서도 중요한 의미를 갖습니다. 이것이 가능한 것으로 조금 더 일반화 된 형태로 특정 자식 클래스등을 처리할 수 있습니다.

function foo(B $b)
{
    return $b->foo();
}

$c = new C();
var_dump(foo($c));

생성자

생성자는 객체를 생성할 때 상태를 초기화할 수 있는 방법을 제공합니다. __construct() 메서드를 사용하여 정의할 수 있으며, 예를 들어 아래와 같은 코드는 message 라는 값을 생성시 받아 상태를 초기화합니다. 생성자가 정의되지 않은 클래스의 경우 기본 생성자가 대신 그 역할을 수행합니다. 암묵적으로 생성됩니다.

class B
{
    public $message;

    public function __construct($message)
    {
        $this->message = $message;
    }
}

$b = new B('Hello, world');
var_dump($b->message); // -> Hello, world

소멸자

소멸자는 C++ 에서 주로 사용하지만, 모던 언어에서는 지원하지 않는 경우가 대부분입니다. PHP 에서는 소멸자 또한 제공할 수 있습니다. 소멸자는 객체가 소멸할 때 호출됩니다. 객체 소멸시 리소스를 해제한다거나 할 때 사용할 수 있을 것입니다. 사용법 자체는 생성자와 동일하며, 대신 메서드의 이름이 __destruct() 이라는 점이 다릅니다.

class A
{
    public function __destruct()
    {
        var_dump(__METHOD__); // -> A::__destruct
    }
}

상속에서의 생성자와 소멸자

상속에서 생성자와 소멸자는 부가 효과가 있는데, 자식 클래스의 생성자가 별로도 정의되어 있지 않은 상황에서 자식 클래스의 인스턴스를 생성하면 부모 클래스의 생성자가 같이 호출됩니다.

class A
{
    public function __construct()
    {
        var_dump(__METHOD__);
    }
}

class C extends A
{
}

$c = new C(); // -> A::__construct

그러나 자식 클래스에 생성자나 소멸자가 있는 경우, parent 문맥 키워드를 통해 부모 클래스의 생성자를 명시적으로 호출해주어야 합니다.

class C extends A
{
    public function __construct()
    {
        parent::__construct();
    }

    public function __destruct()
    {
        parent::__destruct();
    }
}

가시성

가시성은 프로퍼티나 메서드에 대해 외부에서 접근할 수 있는 권리에 대한 이야기입니다. public, private, protected 이렇게 3가지가 있으며 각각 의미하는 바가 다릅니다.

public

클래스 파트를 이야기하면서 프로퍼티나 메서드에 계속 사용했던 가시성입니다. 상속 관계를 포함한 외부에서 접근할 수 있도록 선언합니다. 주로 사용자에게 제공되는 메서드를 public 키워드를 사용하여 정의합니다.

class A
{
    public $public = 'public';
}

$a =  new A();
var_dump($a->public); // -> public

protected

가시성 파트를 상속에 섞어서 이야기하고 있는 이유입니다. 상속 관계에서 접근할 수 있고 외부에서는 접근할 수 없도록 만듭니다.

class A
{
    protected $protected = 'protected';
}
class B extends A
{
    public function __construct()
    {
        var_dump($this->protected); // -> protected
    }
}

private

상속관계를 포함한 외부에서 접근할 수 없도록 만듭니다. 클래스 내부에서만 사용할 수 있도록 합니다.

class A
{
    private $private = 'private';

    public function __construct($private)
    {
        $this->private = $private;
    }
}

Final

클래스 선언시 final 키워드를 함께 적으면 해당 클래스를 또 다른 클래스가 상속받을 수 없습니다. 메서드에 적으면 재정의 할 수 없다는 것을 의미합니다.

상속할 수 없는 클래스

final class A
{
}

// class B extends A
// {
// }

재정의 할 수 없는 메서드

class A
{
    final public function foo()
    {
        var_dump('Hello, world');
    }
}

class B extends A
{
    // public function foo()
    // {
    // }
}

더 읽을거리

PHP: 추상화 (추상 클래스, 인터페이스, 트레이트)

https://www.inflearn.com/course/php7-reboot

https://www.inflearn.com/course/php7-oop

PHP 카테고리 목차 및 문서 정리

2020년, PHP 언어가 가지는 의미

https://www.php.net/manual/en/