2017-09-20 1 views
1

이름을 지정하는 방법을 모르겠지만 여기에 설명되어 있습니다. 가정하자 내가 코드에서 다음PHP OOP 클래스 및 함수

class A { 
    public function aa() { 
     $this->bb(); 
    } 
    public function bb() { 

    } 
} 

class B extends a { 

} 

class C { 
    __construct(B $service) { 
     $this->service = $service; 
    } 
    public function aa() { 

     $this->service->aa(); 
    } 
} 

내 전화가

$C = new C(new B()); 
$C->aa(); 

그래서이 기본적으로 내가 원하는 무엇인가하는 A:aa()를 실행 할 것이다있다. 보시다시피, A::aa() AA::bb()이라고합니다.

내가 필요한 것. AA :: bb()를 호출 할 때 클래스 C에서 정의 된 코드를 실행하려고하지만 A 클래스를 변경할 수 없습니다. B 클래스 또는 C 클래스 만 변경할 수 있습니다.

내 생각이

class B extends a { 
    public $listener; 
    bb() { 
     parent::bb(); 
     $this->listener(); 
    } 
} 

class C { 
    __construct(B $service) { 
     $this->service = $service; 
    } 
    public function aa() { 

     $this->service->listener = function() { } 
     $this->service->aa(); 
    } 
} 

처럼 BB() 함수를 B 클래스에 리스너를 추가하고 덮어했다 그러나 나는 많은, 좋은 일처럼 보이지 않는이 아이디어를 좋아하지 않는다 . 내 옵션은 무엇입니까?

다시 말해서 A 클래스를 변경할 수 없으며 C 클래스 만 호출 할 수 있습니다.

PHP 버전은 5.3

+0

청취자 로직을 클래스 B에 직접 저장할 수 없으므로 너무 많은 옵션이 없습니다. 나는 $ this-> service-> listener = function() {}'을 생성자로 옮깁니다. 왜 싫어하니? –

답변

1

두 가지 옵션이 있습니다. 확장하거나 장식하십시오.

좀 당신은 이미 무엇을 쓸 것입니다,하지만, 내가 청취자에 대한 public 가시성을 사용하지 것이다

먼저 하나

class Foo extends A { 
    private $listener; 
    public function setListener(callable $func) { 
     $this->listener = $func; 
    } 
    public function bb() { 
     call_user_func($this->listener); 
     return parent:bb(); 
    } 
} 

내가 세터 주입을 통해 청취자를 통과 한 예에서,하지만 당신은 또한 사용할 수 있습니다 생성자 주입을 수행하고 오버로드 된 __construct() 메소드의 $listened을 전달합니다. 클래스를 확장하면 "인터페이스 제한 사항"은 생성자의 서명과 관련이 없습니다.

class Foo { 
    private $target; 
    public function __construct(A $target) { 
     $this->target = $target; 
    } 

    public function bb($callback) { 
     $callback(); 
     return $this->target->bb(); 
    } 

    public function __call($method, $arguments) { 
     return call_user_func_array( 
       array($this->target, $method), 
       $arguments 
      ); 
    } 
} 

두 번째 방법은 당신이 인터페이스를 변경 할 것이다 :


다른 방법은 장식을 사용하는 것입니다.

선택하는 옵션은 실제로 구현해야하는 정확한 기능에 따라 다릅니다. 데코레이터는 객체 동작을 크게 변경해야하는 경우에 대한 해결책입니다. 예를 들어, 액세스 제어를 추가하는 것이 좋습니다.

+0

답변 해 주셔서 감사합니다. 이 질문에서 생략 한 것은 실행해야하는 코드가 C 클래스 내부에 있어야한다는 것입니다. 귀하의 예제에서 Foo는 B 클래스 또는 C 클래스입니까? – keepwalking

+0

그것은'B' 클래스입니다. 당신은 애매한 클래스/메소드가 실제로 도움이되지 않습니다. –

1

A 코드가 완료된 후 C에 코드를 실행하고 싶습니다. A를 변경할 수 없습니다.

설명대로 C::aaA::aa을 호출합니다.이 번호는 A::bb이며 스택은 풀립니다. 서비스 호출이 완료된 후 C::aa에서 작업을 수행하는 것이 어떻습니까?

class C { 
    public function aa() { 
     $this->service->aa(); 
     // whatever you want to do 
    } 
} 

A::aa를 호출하지만 A::bb 전에 당신이 명료 충분 게시 한 다음 예를 호출 한 후에 다른 한편으로는, 당신은 코드를 호출 할 필요가있는 경우 :

class B extends a { 
    public $listener; 
    public function bb() { 
     call_user_func($this->listener); 
     parent::bb(); 
    } 
} 

참고를 call_user_func 사용. PHP 5.3에서 멤버 변수에 저장된 익명 함수를 호출하는 데 필요합니다.