Я работаю над следующей версией моей системы согласования языковых ограничений. Я начал с этого ( abstract
объявление функции кажется проблемой):
namespace AAABIT;
abstract class LangPrefSet{
private $LangPrefs;
public function __construct(){$this->LangPrefs=array();}
public function add(LangPref $langpref){$this->LangPrefs[]=$langpref;}
public function langPrefs(){return $this->LangPrefs;}
abstract public function reconcile(LangPrefSet $other);//←Seems to be throwing an error… We don't strictly need this line, but this is a little concerning…
protected static function reconcile_LangPrefSets(LangPrefSet_ForUser $UserLangPrefSet,LangPrefSet_Resource $RsrcLangPrefSet,$maxOptions){//…
}
}
//Following classes are necessary because language similarity is a one-way mapping. Just because resources in Lang A (e.g. Russian) are likely to be readily understandable for speakers/readers of Lang B (e.g. Ukrainian), does not mean that the resources in Lang B (e.g. Ukrainian) are equally intelligible for speakers/readers of Lang A (e.g. Russian)!
class LangPrefSet_For_User extends LangPrefSet{public function reconcile(LangPrefSet_Resource $RsrcLangPrefSet){return self::reconcile_LangPrefSets(self,$RsrcLangPrefSet);}}
class LangPrefSet_Resource extends LangPrefSet{public function reconcile(LangPrefSet_For_User $UserLangPrefSet){return self::reconcile_LangPrefSets($UserLangPrefSet,self);}}
Я думал, что это будет работать, потому что LangPrefSet_Resource соответствует LangPrefSet; но PHP счел это нежелательным, бросив вышеупомянутую ошибку. Я подумал, что мне больше повезет с интерфейсом … Итак, я сделал это:
interface LangPrefSet_Reconcilable{
public function reconcile(LangPrefSet_Reconcilable $other);
}
Затем я сделал два класса, расширяющих LangPrefSet, implements LangPrefSet_Reconcilable
и закомментировал объявление абстрактной функции (после первой попытки сделать это требует LangPrefSet_Reconcilable
параметр типа интерфейса, который также не работал) — результаты:
Fatal error: Declaration of AAABIT\LangPrefSet_For_User::reconcile() must be compatible with AAABIT\LangPrefSet_Reconcilable::reconcile(AAABIT\LangPrefSet_Reconcilable $other)
— Это не проблема для меня, так как я могу просто abstract function
а также interface
и система будет работать нормально. Однако я обеспокоен тем, что мог неправильно понять интерфейсы / абстрактные классы!
Что не так с указанием, что метод класса переопределяет abstract function a(ObjB $b)
или аналогичная спецификация интерфейса, принимает в качестве параметра ObjC $c
где ObjC расширяет ObjB?
Ваш тип параметра должен быть одинаковым в интерфейсе (или абстрактном классе) и там, где вы реализуете то же самое. сейчас интерфейс LangPrefSet_Reconcilable
и реализация говорит LangPrefSet_Resource
а также LangPrefSet_For_User
,
Вы можете использовать второй интерфейс, как показано ниже, или использовать тот же класс.
interface LangPrefSetReconcilableDataInteface {
...
}
interface LangPrefSet_Reconcilable{
public function reconcile(LangPrefSetReconcilableDataInteface $other);
}
class LangPrefSet_Resource implements LangPrefSetReconcilableDataInteface {
...
}
class LangPrefSet_For_User implements LangPrefSetReconcilableDataInteface {
...
}
class LangPrefSet_For_User extends LangPrefSet
{
public function reconcile(LangPrefSetReconcilableDataInteface $RsrcLangPrefSet)
{
return self::reconcile_LangPrefSets(self,$RsrcLangPrefSet);
}
}
class LangPrefSet_Resource extends LangPrefSet
{
public function reconcile(LangPrefSetReconcilableDataInteface $UserLangPrefSet)
{
return self::reconcile_LangPrefSets($UserLangPrefSet,self);
}
}
Проблема может заключаться в том, что в объявлении абстрактного класса я указываю, что любой LangPrefSet
должно быть приемлемым для reconcile()
метод объекта:
abstract public function reconcile(LangPrefSet $other);
— Принимая во внимание фактическое объявление метода, в одном случае я указываю, что только LangPrefSet_Resource
было бы приемлемо, а в другом случае, что только LangPrefSet_For_User
было бы приемлемо.
Поэтому объявления метода объекта несовместимы с объявлением абстрактного метода.. Кажется, что правильное применение этих методов объявления интерфейса / абстрактного метода не состоит в расширении диапазона допустимых ограничений типов параметров в классах, которые реализуют интерфейс, поскольку мы можем достичь этого просто объявив входные ограничения, какими они должны быть для них. конкретные классы / методы; скорее, объявления интерфейса / абстрактного метода предназначены для расширения диапазона параметров, которые могут фактически передаваться методу, который определяет эти абстрактные типы параметров.