Page tree

자바나 C++ 같은 객체 지향 언어에서 오버로딩(Overloading)은 메소드 이름은 동일하지만 파라미터가 달라서 같은 이름의 메소드를 용도별로 호출할 수 있는 기능을 의미합니다.


예로 다음과 같이 add 라는 메소드는 이름이 같지만 파라미터 타입이 다른 여러 개의 메소드가 존재할 수 있습니다.

public int add(int lhs, int rhs) {
    return lhs + rhs;
}

public float add(float lhs, float rhs)   {
    return lhs + rhs;
}


하지만 PHP 에서 오버로딩은 동적으로 메소드(method)나 프로퍼티(property)를 생성하는 것을 의미합니다. 이는 실행 시점에 메소드나 프로퍼티가 없어도 동적으로 생성할 수 있으므로 클래스를 임의로 확장할 수 있습니다.

먼저 프로퍼티 오버로딩을 살펴 보면 PHP의 예약 함수인 __set, __get, __isset, __unset 을 통해 이루어 집니다.

<?php
class PropertyTest {
	// 오버로딩된 프로퍼티 저장
	private $data = array();
	public function __set($name, $value)
    {           
		$this->data[$name] = $value;
    }
	public function __get($name)
    {           
		if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }
		// 없을 경우 에러 처리 코드
        throw new UnexpectedValueException($name . ' 알수 없는 프로퍼티입니다.');
    }
}

$prop = new PropertyTest ();
$prop->name = 'lesstif';
echo $prop->name;	// lesstif 라는 문자열 출력
echo $prop->email; // undefined variable 경고가 출력됨.

위 코드를 실행하면 name 이라는 프로퍼티가 생성되었으므로 lesstif 라는 문자열이 출력되고 email 이라는 프로퍼티는 없으므로 UnexpectedValueException 가 던져집니다.

$ php PropertyTest.php
 
lesstif
Fatal error: Uncaught exception 'UnexpectedValueException' with message 'email
알수 없는 프로퍼티입니다.' in D:\laravel\laravel5-programming\chap1\PropertyTest
.php on line 16
UnexpectedValueException: email 알수 없는 프로퍼티입니다. in D:\laravel\laravel5
-programming\chap1\PropertyTest.php on line 16

프로퍼티 오버로딩을 사용하면 위와 같이 런타임에 프로퍼티가 생성되고 사용할 수 있는 것을 알수 있습니다.


메소드 오버로딩의 경우 일반 메소드는 __call() 메소드를 스태틱 메소드는 __callStatic 을 구현하면 됩니다. 예로 다음과 같은 예제 코드를 봅시다.

<?php
class MethodTest {
	public function __call($name, $arguments)
    {    
        echo "일반 메소드 호출: $name' ";
		echo "아규먼트 " . implode(', ', $arguments). "\n";
    } 
	public static function __callStatic($name, $arguments)
	{
        echo "정적 메소드 호출: '$name' ";
		echo "아규먼트 " . implode(', ', $arguments). "\n";
	}
}
 
// 클래스내 메소드로 호출
$obj = new MethodTest ();
$obj->whereName('name', 'lesstif');
 
// 정적 함수로 호출
MethodTest ::whereName('name', 'lesstif');

MethodTest 클래스에 없는 메소드인 whereName을 클래스내 메소드 또는 정적 함수처럼 호출하면 PHP 인터프리터가 자동으로 생성합니다.


위 파일을 실행시키면 다음과 같은 결과가 출력됩니다.

$ php MethodTest.php
 
일반 메소드 호출: 이름 'whereName' 아규먼트 name, lesstif
정적 메소드 호출: 이름 'whereName' 아규먼트 name, lesstif

PHP 의 오버로딩은 일반적인 OOP 언어와 다른 의미로 사용되어 다른 언어 사용자는 혼란스러울 수 있으므로 "동적 메소드 및 프로퍼티 생성" 기능이라고 이해하면 됩니다.

런타임에 임의의 메소드와 프로퍼티를 소스 수정없이 만들 수 있으므로 유연함과 확장성을 제공하며 라라벨은 내부적으로 여러 부분에 오버로딩을 사용하고 있습니다.


실제로 테이블에서 where 조건으로 데이타를 가져와야 하는 경우 클래스에 where() 와 orWhere() 메소드만 있어도 이를 사용하여 다음과 같은 동적 메소드를 런타임에 생성하여 실행할 수 있습니다.

// users 테이블에서 (사용자 이름 또는 이메일) 그리고 우편번호로 조회
User::where('username', $name)->orWhere('email', $email)->where('zipcode', $zipcode);
 
// 위와 동일한 조건을 메소드 오버로딩 사용하여 동적 메소드 생성하여 조회
User::whereUsernameOrEmailAndZipcode($name, $email, $zipcode); 


사용자가 오버로딩을 직접 작성할 일이 많지는 않지만 라라벨을 잘 쓰기 위해서는 꼭 이해해야할 PHP 의 기능이고 혹시 라라벨 소스를 볼 일이 생길 경우  호출한 메소드가 소스에 없어도 놀라지 않기를 바랍니다.


PHP의 오버로딩 용어는 다른 객체 지향 언어의 사용자들은 혼란스러울 수 있으므로 향후 이 기능을 다룰 경우 동적 프로퍼티/메소드 생성 이라고 명명하겠습니다.

Ref