php Как реализовать "конструктор" в трейте -- для значений которые нужно инициллизировать один раз (trait)
Primary tabs
Предположим, что у был класс, которому для печати данных разными методами в своем конструкторе приходилось (чтобы не создавать объект каждый раз) одному из своих полей (->outputWriter) присваивать объект конкретного класса (\Codeception\Lib\Console\Output), занимающегося печатью, после чего данное поле использовалось методами:
class IFFAcceptanceTester extends \AcceptanceTester { public function __construct(\Codeception\Scenario $scenario) { parent::__construct($scenario); $this->outputWriter = new \Codeception\Lib\Console\Output([]); } /** * Хранит класс, с помощью которого можно писать в консоль * @var \Codeception\Lib\Console\Output */ protected $outputWriter = null; /** * Специальный маркер для перевод строки один раз за время работы теста * * @var boolean */ protected $newLineAlreadyExists = false; /** * Log additinal info into console * Вывод дополнительной технической информации о процессе работы теста в консоль. * * Поддерживает тэги symfony/console @link https://symfony.com/doc/current/console/... * * @param type $str */ public function log($str) { $this->checkNewLineNeed(); $message ="⚑ $str"; // echo ("$message \n"); $this->outputWriter->writeln("$message"); } /** * Обёртка над print_r() для тестировщика $I * * @param type $value * @param string $comment */ public function pre($value, $comment = '') { $this->checkNewLineNeed(); if ($comment) { $comment .= ':'; } $message =" $comment " . print_r($value, true); $this->outputWriter->writeln("$message"); } /** * Вызывается один раз для перевода строки после вывода имени теста */ protected function checkNewLineNeed() { if (!$this->newLineAlreadyExists) { echo "\n"; $this->newLineAlreadyExists = true; } } }
Теперь мы хотим вынести те же методы ->log() и ->pre() в трейт, а с ними и то, на что они опираются -- ведь это позволит использовать логгирование, не только в классах тестера, но и в других независимых от него модулях системы.
Для этого делаем следующее:
- Для инициаллизации $this->outputWriter заводим специальный метод -- назовем его, что не удивительно, outputWriter(), который просто проверяет инициллизировано ли уже значение
- Заменяем все обращения
$this->outputWriter
заменям на вызов
$this->outputWriter()
(уже метода)
В результате получаем:
trait IFFLoggerTrait { /** * Хранит класс, непосредственно занимающийся печать. * @var object */ protected $outputWriter = null; protected function outputWriter() { if (!$this->outputWriter) { // если ещё не инициллизировано $this->outputWriter = new \Codeception\Lib\Console\Output([]); } return $this->outputWriter; } /** * Специальный маркер для перевод строки один раз за время работы теста * * @var boolean */ protected $newLineAlreadyExists = false; /** * Log additinal info into console * Вывод дополнительной технической информации о процессе работы теста в консоль. * * Поддерживает тэги symfony/console @link https://symfony.com/doc/current/console/... * * @param type $str */ public function log($str) { $this->checkNewLineNeed(); $message ="⚑ $str"; // echo ("$message \n"); $this->outputWriter()->writeln("$message"); } /** * Обёртка над print_r() для тестировщика $I * * @param type $value * @param string $comment */ public function pre($value, $comment = '') { $this->checkNewLineNeed(); if ($comment) { $comment .= ':'; } $message ="$comment " . print_r($value, true); $this->outputWriter()->writeln("$message"); } /** * Вызывается один раз для перевода строки после вывода имени теста */ protected function checkNewLineNeed() { if (!$this->newLineAlreadyExists) { echo "\n"; $this->newLineAlreadyExists = true; } } }
- Log in to post comments
- 4499 reads