私はいくつかのデザインパターンで遊んでいて、SPLのオブザーバーパターンを使用して例を作成したいと思いました。オブザーバーとサブジェクトを完全に一般化することは意味がないため、インターフェイスを拡張して、手元のアプリケーションに固有のものにしたいと思いました。問題は、以下のコードを実行すると、「DataAccess :: update()はSplObserver :: update()のコードと互換性がある必要があります」などのエラーが発生することです。
メソッドのシグネチャをインターフェイスのシグネチャと一致するように切り替えることで、このコードをエラーなしで実行できることを知っています。私の質問はこれです:なぜそれは署名で定義されたクラスの子を許可しないのですか? 以下では、ModelObserverはSplObserverであり、ModelはSplSubjectです。私はこれがうまくいくと思っていたでしょう。私は何かが足りないのですか?
参考までに、インターフェイスで定義されている明示的なメソッドシグネチャを使用し、コードロジックでinstanceofキーワードを使用して同じことを実現できることはわかっています。もっとエレガントな解決策を見つけたいと思っていました。ありがとう!
<?php
interface ModelObserver extends SplObserver {
}
class DataAccess implements ModelObserver {
/*
* (non-PHPdoc) @see SplObserver::update()
*/
public function update(Model $subject) {
// TODO Auto-generated method stub
}
}
// Just a generic model for the example
class Model implements SplSubject {
private $_properties = array ();
private $_observers = array ();
/*
* generically handle properties you wouldn't want to do it quite like this
* for a real world scenario
*/
public function __get($name) {
return $this->_properties [$name];
}
public function __set($name, $value) {
$this->_properties [$name] = $value;
}
public function __call($method, $args) {
if (strpos ( $method, 'get' ) === 0) {
$name = lcfirst ( str_replace ( 'get', '', $method ) );
return $this->_properties [$name];
}
if (strpos ( $method, 'set' ) === 0) {
$name = lcfirst ( str_replace ( 'set', '', $method ) );
$this->_properties [$name] = $args [0];
return $this;
}
}
public function __toString() {
return print_r ( $this, true );
}
/*
* (non-PHPdoc) @see SplSubject::attach()
*/
public function attach(ModelObserver $observer) {
$this->_observers [] = $observer;
return $this;
}
/*
* (non-PHPdoc) @see SplSubject::detach()
*/
public function detach(ModelObserver $observer) {
if (in_array ( $observer, $this->_observers )) {
$f = function ($value) {
if ($value != $observer) {
return $value;
}
};
$observers = array_map ( $f, $this->_observers );
}
return $this;
}
/*
* (non-PHPdoc) @see SplSubject::notify()
*/
public function notify() {
foreach ($this->_observers as $observer) {
$observer->update($this);
}
}
}
$da = new DataAccess();
$model = new Model ();
$model->setName ( 'Joshua Kaiser' )->setAge ( 32 )->setOccupation ( 'Software Engineer' )
->attach($da);
echo $model;