PHP에서 제공하는 "오버로딩"은 클래스 속성과 메서드를 동적으로 "생성"하는 것을 의미합니다. 우리는 마법의 방법을 통해 이를 수행합니다.
현재 환경에서 정의되지 않았거나 보이지 않는 클래스 속성이나 메서드를 호출할 때 오버로드된 메서드가 호출됩니다.
오버로드된 모든 메서드는 공개로 선언되어야 합니다.
참고:
1) 이러한 매직 메소드의 매개변수는 참조로 전달될 수 없습니다.
2) PHP의 "오버로딩"은 대부분의 다른 객체 지향 언어와 다릅니다. 전통적인 "오버로딩"은 동일한 이름을 가진 여러 클래스 메서드를 제공하는 데 사용되지만 각 메서드의 매개 변수 유형과 개수는 다릅니다.
속성 오버로딩
public void__set(string$name, mixed$value) publicmixed__get(string$name) publicbool__isset(string$name) publicvoid__unset(string$name)
액세스할 수 없는 속성에 값을 할당하면 __set()가 호출됩니다.
액세스할 수 없는 속성의 값을 읽을 때 __get()이 호출됩니다.
액세스할 수 없는 속성에 대해 isset() 또는 empty()가 호출되면 __isset()가 호출됩니다.
액세스할 수 없는 속성에 대해 unset()이 호출되면 __unset()이 호출됩니다.
$name 매개변수는 연산할 변수의 이름을 나타냅니다. __set() 메서드의 $value 매개 변수는 $name 변수의 값을 지정합니다.
속성 오버로드는 객체에서만 수행할 수 있습니다. 정적 메서드에서는 이러한 매직 메서드가 호출되지 않습니다. 따라서 이러한 메서드 중 어느 것도 정적으로 선언할 수 없습니다. PHP 5.3.0부터 이러한 매직 메서드를 정적으로 정의하면 경고가 생성됩니다.
참고:
PHP가 할당 작업을 처리하는 방식으로 인해 __set()의 반환 값은 무시됩니다. 마찬가지로 다음 체인 할당에서는 __get()이 호출되지 않습니다.
$a = $obj->b = 8;
참고:
오버로드된 속성 isset()을 제외한 다른 언어 구성에서는 사용할 수 없습니다. 즉, 오버로드된 속성에 empty()를 사용할 때 오버로드된 매직 메서드가 호출되지 않습니다.
이러한 제한을 피하려면 오버로드된 속성을 지역 변수에 할당한 다음 비어 있음()을 사용해야 합니다.
예제 #1 속성 오버로드에 __get(), __set(), __isset() 및 __unset() 사용
class PropertyTest{ /*被重载的数据保存在此*/ private $data = array(); /*重载不能被用在已经定义的属性*/ public $declared = 1; /*只有从类外部访问这个属性时,重载才会发生*/ private $hidden = 2; public function __set($name,$value) { echo "Setting '$name' to '$value'<br>"; $this->data[$name] = $value; } public function __get($name) { echo "Getting '$name'<br>"; if(array_key_exists($name,$this->data)){ return $this->data[$name]; } $trace = debug_backtrace(); trigger_error('未知属性 via __get():'.$name.' in '.$trace[0]['file'].' on line '.$trace[0]['line'], E_USER_NOTICE); return null; } /*PHP5.1.0之后的版本*/ public function __isset($name){ echo "Is '$name' set?<br>"; return isset($this->data[$name]); } /*PHP5.1.0之后的版本*/ public function __unset($name){ echo "Unsetting '$name'<br>"; unset($this->data[$name]); } /*非魔术方法*/ public function getHidden(){ return $this->hidden; } } echo '<pre class="brush:php;toolbar:false">'; $obj = new PropertyTest; $obj->a = 1; echo $obj->a.'<br>'; var_dump(isset($obj->a)); unset($obj->a); echo '<br>'; echo $obj->declared.'<br>'; echo "Let's experiment with the private property named 'hidden':<br>"; echo "Privates are visible inside the class,so __set() not used...<br>"; echo $obj->getHidden().'<br>'; echo "Privates not visible outside of class,so __get() is used...<br>"; echo $obj->hidden;
출력 결과:
'a' 설정 '1'로
'a' 가져오기
1
'a'가 설정되어 있나요?
bool(true)
'a'를 설정하지 않음
1
'hidden'이라는 개인 속성을 실험해 보겠습니다.
개인 속성은 클래스 내부에 표시되므로 __set()는 사용되지 않습니다...
2
Private는 클래스 외부에서는 볼 수 없으므로 __get()을 사용합니다...
'숨김' 가져오기
메서드 오버로딩
public mixed __call ( string$name , array$arguments ) public static mixed __callStatic ( string$name , array$arguments )
객체에서 액세스할 수 없는 메서드가 호출되면 __call()이 호출됩니다.
정적 모드에서 액세스할 수 없는 메서드를 호출하면 __callStatic()이 호출됩니다.
$name 매개변수는 호출할 메소드의 이름입니다. $arguments 매개변수는 $name 메소드에 전달될 매개변수를 포함하는 열거형 배열입니다.
예제 #2 __call() 및 __callStatic()을 사용하여 메서드 오버로드
class MethodTest { public function __call($name,$arguments) { //注意:$name的值区分大小写 echo "Calling object method '$name' ".implode(',',$argument).'<br>'; } //PHP5.3.0之后的版本 public static function __callStatic($name,$arguments) { //注意:$name的值区分大小写 echo "Calling static method '$name' ".implode(',',$argument).'<br>'; } } $obj = new MethodTest; $obj -> runTest('in object context'); MethodTest::runTest('in static context');
출력 결과:
객체 메서드 'runTest' 호출
객체 메소드 'runTest' 호출