1. 마법의 방법:
1.__get,__set
__get: 액세스할 수 없는 속성을 가져올 때 트리거됩니다(액세스할 수 없다는 것은 속성이 존재하지 않거나 액세스 권한이 없음을 의미합니다 )
__set: 액세스할 수 없는 속성에 값을 할당할 때 트리거됩니다.
2.__isset,__unset
__isset: isset() 함수를 사용하여 액세스할 수 없는 속성이 결정될 때 트리거됩니다.
__unset: unset() 함수를 사용하여 액세스할 수 없는 속성을 조작할 때 트리거됩니다.
3.__call,__callStatic
__call: 액세스할 수 없는 메서드가 호출될 때 트리거됩니다.
__callStatic: 액세스할 수 없는 정적 메서드가 호출될 때 트리거됩니다.
4.__construct,__destruct
__construct: 객체를 초기화할 때 트리거됩니다.
__destruct: 객체가 파괴되거나 스크립트가 실행될 때 트리거됩니다.
5.__자동 로드
__autoload: 액세스할 수 없는 클래스가 사용될 때 트리거됩니다.
6.__클론
__clone: 객체가 복제될 때 트리거됩니다.
7.__자고__자고
__sleep: 직렬화가 사용될 때 트리거됨
__wakeup: unserialize를 사용할 때 트리거됩니다.
8.__toString,__invoke
__toString: 객체가 문자열로 작동할 때 트리거됩니다. 예를 들어 $obj가 객체인 경우 echo $obj는 __toString
을 트리거합니다.__invoke: 객체가 함수로 사용될 때 트리거됩니다. $obj가 객체인 경우 $obj()는 __invoke를 트리거합니다
2. 지연된 정적 바인딩
개념은 제쳐두고 예를 살펴보고 이해하세요.
지연된 정적 바인딩은 처음에 어떻게 나타났나요? 다음 예를 참조하세요.
class A{<br>}<br>class B extends A{<br> public static function out(){<br> return new self();<br> }<br>}<br>class C extends A{<br> public static function out(){<br> return new self();<br> }<br>}<br>var_dump(B::out());//结果是object(B)#1 (0) { }<br>var_dump(C::out());//结果是object(C)#1 (0) { }<br>然后我们将子类中相同的代码抽取到父类class A中,变成:
class A{<br> public static function out(){<br> return new self();<br> }<br>}<br>class B extends A{<br>}<br>class C extends A{<br>}<br>var_dump(B::out());//结果是object(A)#1 (0) { }<br>var_dump(C::out());//结果是object(A)#1 (0) { }<br>这个结果显然不是我们想要的,这里的问题主要是因为self指代的是它所在的类.这里self在类A里面,所以返回的永远是类A的对象,<br>而我们想要的是让out()方法返回调用它的类的对象而不是它所在的类的对象.怎么办?<br>此时我们马上可以想到$this可以代表调用它的对象,但是out()是一个静态方法,里面是不能出现$this的,怎么办?<br>用static.它也代表调用它的对象如:
class A{<br> public static function out(){<br> return new static();<br> }<br>}<br>class B extends A{<br>}<br>class C extends A{<br>}<br>var_dump(B::out());//结果是object(B)#1 (0) { }<br>var_dump(C::out());//结果是object(C)#1 (0) { }<br>这样就好了.这就是延迟静态绑定.<br><br>在看下面的例子:
왜 이런 결과가 나온 걸까요? 분석해 보겠습니다.
먼저 객체 c는 get() 메소드를 호출했지만 C 클래스에는 없으므로 B 클래스에서 찾아서 찾은 다음 get 메소드를 실행합니다.
A::foo()를 먼저 실행합니다. 클래스 A는 자신의 foo()를 직접 호출하고 `fooA`를 출력한 다음 호출합니다. 분명히 여기에서 static::out()을 호출하는 것은 클래스 A입니다. 출력 클래스 이름도 A입니다. (여기서는 클래스 A에 초점을 맞춥니다)
그런 다음 parent::foo()를 실행합니다. 여기서는 클래스 A의 foo()가 실행되고 `fooA`가 출력된 다음 static::out()이 실행됩니다. 이번에는 정적 호출자가 클래스 A가 아니라 클래스 C입니다. 왜냐하면 parent는 부모 클래스를 나타내지만 특정 클래스를 나타내지는 않기 때문입니다(여기서는 부모 클래스가 누구인지에 관계없이 부모 클래스의 메서드에 중점을 둡니다).
그런 다음 self::foo()를 실행합니다. self는 자신이 속한 클래스(클래스 B)를 나타냅니다. 상위 클래스에서 찾지 않고 먼저 foo()를 실행하므로 `fooA`를 출력한 다음 static을 실행합니다. :out()도 같은 이유로 여기에 사용된 static은 클래스 A가 아닌 클래스 C입니다. self는 클래스 B를 나타내지만 self는 특정 클래스를 나타낼 수 없습니다.
간단히 말하면: 객체 c가 get()-->A::foo()를 실행하기 시작합니다. 이때 체인이 끊어지고 다음과 같이 됩니다. 클래스 A에서 직접 foo()를 호출하면 객체 c와는 아무런 관련이 없습니다. 물론 여기서 static은 클래스 A를 나타냅니다.
다음으로, 클래스 A의 객체 c-->parent::foo()--> foo()-->static::out() 퉁명스럽게 말하면 여기서 parent는 포인팅 함수입니다. 즉, 누구의 foo() 메소드가 실행되는지를 보면 객체 c가 클래스 A의 foo 메소드를 호출한다는 것을 알 수 있습니다. 그러면 foo의 static은 클래스 C를 나타냅니다.
마지막으로, 클래스 A의 객체 c-->self::foo()-->foo()-->static::out() 위와 동일합니다. 여기 self에도 포인팅 기능이 있습니다. , 그러나 우리는 마침내 클래스 A에 도달합니다. 객체 c가 클래스 A의 foo 메소드를 호출한다는 것을 이해할 수 있습니다. 그러면 foo의 static은 클래스 C를 나타냅니다
<br><br>