@ninjjjja

Как расширить возвращаемый библиотекой класс?

Добрый день.

Есть некая php-библиотека, которая реализует некие классы:
class Foo {
	public $bar;

	function __construct( ) { $this->bar = new Bar; }	
	function getBar( ) { return $this->bar; }	
}

class Bar {
	// some other code
}


Клиентский код в свою очередь хочет расширить класс Bar своим кастомным кодом:
class BarEx extends Bar {
	// some other code
}


Напрямую он этого сделать не может, поскольку библиотека все равно будет возвращать Bar, а не BarEx.

Он может использовать фасад - но это не очень удобно, потому что таких классов десятки, и делать фасад под каждый - проблема. И все равно придётся на каждый вызов функции писать дополнительный код для создания этого фасада.

Вопрос: каким образом решается такая проблема? Например, DomDocument для этого имеет метод registerNodeClass - но как он работает под капотом и нормальная ли это практика?

Должен ли создатель библиотеки давать возможность перезаписывать внутренние классы, и создавать объекты не как new Bar, а, например, как new static::CustomBarClassName?

Нормальный ли это код?
class Foo {
	static protected $BarClassName = Bar::class;
	public $bar;

	static public function registerBarClass( $new_class ) {
		static::$BarClassName = $new_class;
	}

	function __construct( ) { $this->bar = new static::$BarClassName; }
	function getBar( ) { return $this->bar; }
}

class Bar {
	// some other code
}

// ...

Foo::registerBarClass( BarEx::class );
$foo = new Foo;
$bar_ex = $foo->getBar( );
  • Вопрос задан
  • 70 просмотров
Пригласить эксперта
Ответы на вопрос 2
SilenceOfWinter
@SilenceOfWinter Куратор тега PHP
та еще зажигалка...
Я понимаю что ты рос в местах лишения интернета т.ч. для начала гугли "php factory template" и/или "php builder template".

Он может использовать фасад - но это не очень удобно, потому что таких классов десятки, и делать фасад под каждый - проблема.

это говорит о том, что ты не до конца(или вообще) понял идею шаблона facade.

Нормальный ли это код?

Нет, не надо смешивать статику и объекты + нет проверки наследственности класса. Используй классы-фабрики\строители вместо аналогичных методов или внедрение зависимостей(что-то вроде https://php-di.org)
Ответ написан
@Dr03d
Лисков грустя слезинку утирает.
Первый код жестковат, вместо Bar подсунуть BarEx не позволит. Но если бы вместо него было что-то вроде
class Foo {
  protected $bar;

  function __construct($barInheritor ) { 
    if (is_subclass_of($barInheritor, 'Bar') {
      $this->bar = new $barInheritor; }
    }	
  function getBar( ) { return $this->bar; }	
}

уже было бы легче.
Нужно только не забывать про Пространства имён.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы