Я пишу обычай система расширений для php, которая позволяет определять класс с новой функцией для существующего класса и добавлять указанные функции в класс после его определения.
Как уже говорилось, расширения написаны как отдельный класс, давайте назовем один MyExtension
и скажем, что это расширение распространяется на существующие классы, MyExtendedClass1
а также MyExtendedClass2
, Так MyExtension
добавляет некоторые функции MyExtendedClass1
А ТАКЖЕ MyExtendedClass2
,
То, что я хочу сделать, это позволить пользователям вводить подсказку базы на MyExtension.
// $object is guaranteed to either be an instance of MyExtension
// or be a class that is extended with MyExtension
function someFunction(MyExtension $object) {
}
$post = new MyExtendedClass1(); // Is extended by MyExtension
someFunction($post);
$post = new MyExtendedClass2(); // Is extended by MyExtension
someFunction($post);
Что мне интересно, так это:
Есть ли способ «добавить тип к объекту»? Есть ли способ обмануть проверку типов, чтобы разрешить эти вызовы.
Трудно понять твой вопрос, потому что тебе нужно пользовательское расширение описанный как индивидуально расширенный объект.
Если тебе надо some_function для работы с различными типами он не может использовать их напрямую, а подсказка типа не может определить конкретный тип — используйте интерфейс.
Ваши типы должны быть расширены функциональностью общего интерфейса, от которого может зависеть эта функция — используйте объекты-оболочки, которые реализуют один и тот же интерфейс, но знают (как взаимодействовать) конкретный тип.
interface MyExtensionInteface {
public function doSoemthingSpecial();
}
function some_function(MyExtensionInterface $myExtension) {
$myExtension->doSomethingSpecial();
}
class MyExtensionOfExtendedClass1 implements MyExtensionInteface
{
public function __construct(MyExtendedClass1 $obj) {
$this->extended = $obj;
}
public function doSomethingSpecial() {
//...with MyExtendedClass1 type
}
}
class MyExtensionOfExtendedClass2 impements MyExtensionInterface
{
public function __construct(MyExtendedClass2 $obj) {
$this->extended = $obj
}
public function doSomethingSpecial() {
//...with MyExtendedClass2 type
}
}
$a = new MyExtensionOfExtendedClass1(new MyExtendedClass1());
some_function($a);
$b = new MyExtensionOfExtendedClass2(new MyExtendedClass2());
some_function($b);
Именование «расширение» предназначено только для контекста вопроса — оно должно иметь значение реального объекта. Например: DuckSoup(Duck)
+ ChickenSoup(Chicken)
+ function:cook(Soup)
Других решений пока нет …