오버로딩

PHP 에서 오버로딩의 의미는 동적으로 프로퍼티나 메서드를 생성함을 의미합니다. 이러한 동적 엔터티들은 클래스의 매직 메서드를 통해 다양한 형태로 처리됩니다.

오버로딩 기능은 현재 스코프에서 정의되지 않거나 보이지 않는 프로퍼티나 메서드를 조작하려고 할때 호출됩니다. 이 문서에서는 접근불가 프로퍼티 와 접근불가 메서드를 위의 내용을 지칭하는데 사용하겠습니다.

모든 오버로딩 메서드는 public으로 정의되어야 합니다.

메모: 매직 매서드의 인자는 참조 전달이 될 수 없습니다.

메모: PHP의 오버로딩에 대한 해석은 다른 대부분의 객체 지향 언어들과는 다릅니다. 일반적으로는 오버로딩은 동일한 이름을 사용하여 인자의 갯수와 타입을 달리하여 다중으로 메서드를 정의할 수 있는 기능을 의미합니다.


프로퍼티 오버로딩

public __set(string $name, mixed $value): void

public __get(string $name): mixed

public __isset(string $name): bool

public __unset(string $name): void

__set()은 접근불가 프로퍼티에 쓰기를 할때 실행됩니다.

__get()은 접근불가 프로퍼티에서 읽기를 할때 사용합니다.

__isset()은 접근불가 프로퍼티에 대해 isset()empty()가 호출되었을때 불려집니다.

__unset()은 접근불가 프로퍼티를 unset() 했을때 호출됩니다.

$name 인자는 다루고자 하는 프로퍼티 이름입니다. __set() 메서드의 $value 인자는 $name의 값으로 세팅하고자 하는 값입니다.

프로퍼티 오버로딩은 객체 컨텍스트내에서만 동작합니다. 이 매직메서드들은 정적 컨텍스트내에서는 불려지지 않을 것입니다. 게다가 이 메서드들은 static으로 선언할 수 없습니다. PHP 5.3.0 이후로는 매직 오버로딩 메서드가 static으로 선언되어 있을경우 경고를 발생합니다.

Note:__set()의 리턴값은 무시됩니다. 이것은 PHP가 할당연산을 처리하는 방식에 기인합니다. 비슷하게, 연결된 할당은 __get()을 절대 호출하지 않습니다. 예:

$a = $obj->b = 8;

예제 #1 __get(), __set(), __isset()__unset() 메서드로 프로퍼티 오버로딩하기

                  
<?php
class PropertyTest
{
    /**  Location for overloaded data.  */
    private $data = array();

    /**  Overloading not used on declared properties.  */
    public $declared = 1;

    /**  Overloading only used on this when accessed outside the class.  */
    private $hidden = 2;

    public function __set($name, $value)
    {
        echo "Setting '$name' to '$value'\n";
        $this->data[$name] = $value;
    }

    public function __get($name)
    {
        echo "Getting '$name'\n";
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }

        $trace = debug_backtrace();
        trigger_error(
            'Undefined property via __get(): ' . $name .
            ' in ' . $trace[0]['file'] .
            ' on line ' . $trace[0]['line'],
            E_USER_NOTICE);
        return null;
    }

    public function __isset($name)
    {
        echo "Is '$name' set?\n";
        return isset($this->data[$name]);
    }

    public function __unset($name)
    {
        echo "Unsetting '$name'\n";
        unset($this->data[$name]);
    }

    /**  Not a magic method, just here for example.  */
    public function getHidden()
    {
        return $this->hidden;
    }
}


echo "<pre>\n";

$obj = new PropertyTest;

$obj->a = 1;
echo $obj->a . "\n\n";

var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n";

echo $obj->declared . "\n\n";

echo "Let's experiment with the private property named 'hidden':\n";
echo "Privates are visible inside the class, so __get() not used...\n";
echo $obj->getHidden() . "\n";
echo "Privates not visible outside of class, so __get() is used...\n";
echo $obj->hidden . "\n";
?>
                  
                

위의 예는 다음을 출력합니다.

Setting 'a' to '1'
Getting 'a'
1

Is 'a' set?
bool(true)
Unsetting 'a'
Is 'a' set?
bool(false)

1

Let's experiment with the private property named 'hidden':
Privates are visible inside the class, so __get() not used...
2
Privates not visible outside of class, so __get() is used...
Getting 'hidden'


Notice:  Undefined property via __get(): hidden in  on line 70 in  on line 29
                

메서드 오버로딩

public __call(string $name, array $arguments): mixed

public static __callStatic(string $name, array $arguments): mixed

__call()은 오브젝트 컨텍스트내에서 접근불가 메서드를 호출할때 불려집니다.

__callStatic()은 정적 컨텍스트내에서 접근불가 메서드를 호출할때 불려집니다.

$name인자는 불려질 메서드의 이름입니다. $arguments$name 메서드로 전달될 파라미터 배열입니다.

예제 #2 __call()__callStatic()로 메서드 오버로딩하기

                  
<?php
class MethodTest
{
    public function __call($name, $arguments)
    {
        // Note: value of $name is case sensitive.
        echo "Calling object method '$name' "
             . implode(', ', $arguments). "\n";
    }

    public static function __callStatic($name, $arguments)
    {
        // Note: value of $name is case sensitive.
        echo "Calling static method '$name' "
             . implode(', ', $arguments). "\n";
    }
}

$obj = new MethodTest;
$obj->runTest('in object context');

MethodTest::runTest('in static context');
?>
                  
                

위의 예는 다음을 출력합니다.

Calling object method 'runTest' in object context
Calling static method 'runTest' in static context