Глава 30: наследование (черновик)

This commit is contained in:
Igor Simdyanov
2022-05-21 18:44:09 +03:00
parent fdea14082d
commit 31414c1433
20 changed files with 455 additions and 0 deletions

15
inherit/anonym.php Normal file
View File

@ -0,0 +1,15 @@
<?php
class Dumper
{
public static function print($obj)
{
print_r($obj);
}
}
Dumper::print( new class {
public $title;
public function __construct(){
$this->title = 'Hello world!';
}
});

26
inherit/anonym_nested.php Normal file
View File

@ -0,0 +1,26 @@
<?php
class Container
{
private $title = 'Класс Container';
protected $id = 1;
public function anonym()
{
return new class($this->title) extends Container
{
private $name;
public function __construct($title)
{
$this->name = $title;
}
public function print()
{
echo "{$this->name} ({$this->id})";
}
};
}
}
(new Container)->anonym()->print();

27
inherit/file/logger.php Normal file
View File

@ -0,0 +1,27 @@
<?php
class FileLogger
{
public $f; // открытый файл
public $name; // имя журнала
public $lines = []; // накапливаемые строки
public $t;
public function __construct($name, $fname)
{
$this->name = $name;
$this->f = fopen($fname, 'a+');
}
public function __destruct()
{
fputs($this->f, join('', $this->lines));
fclose($this->f);
}
public function log($str)
{
$prefix = '[' . date('Y-m-d_h:i:s ') . "{$this->name}] ";
$str = preg_replace('/^/m', $prefix, rtrim($str));
$this->lines[] = $str . PHP_EOL;
}
}

View File

@ -0,0 +1,31 @@
<?php
// Вначале подключаем "базовый" класс
require_once 'file/logger.php';
// Класс, добавляющий в FileLogger новую функциональность
class FileLoggerDebug extends FileLogger
{
// Конструктор нового класса. Просто переадресует вызов
// конструктору базового класса, передавая немного другие
// параметры.
public function __construct($fname)
{
// Такой синтаксис используется для вызова методов базового класса.
// Обратите внимание, что ссылки $this нет! Она подразумевается.
parent::__construct(basename($fname), $fname);
// Здесь можно проинициализировать другие свойства текущего
// класса, если они будут
}
// Добавляем новый метод
public function debug($s, $level = 0)
{
$stack = debug_backtrace();
$file = basename($stack[$level]['file']);
$line = $stack[$level]['line'];
// Вызываем функцию базового класса
$this->log("[at $file line $line] $s");
}
// Все остальные методы и свойства наследуются автоматически!
}

View File

@ -0,0 +1,32 @@
<?php
// Вначале подключаем "базовый" класс
require_once 'file/logger.php';
// Класс, добавляющий в FileLogger новую функциональность
class FileLoggerDebug0
{
// Объект "базового" класса FileLogger
private $logger;
// Конструктор нового класса. Создает объект FileLogger.
public function __construct($name, $fname)
{
$this->logger = new FileLogger($name, $fname);
// Здесь можно проинициализировать другие свойства текущего
// класса, если они будут
}
// Добавляем новый метод
public function debug($s, $level = 0)
{
$stack = debug_backtrace();
$file = basename($stack[$level]['file']);
$line = $stack[$level]['line'];
$this->logger->log("[at $file line $line] $s");
}
// Оставляем на месте старый метод log()
public function log($s) { return $this->logger->log($s); }
// И такие методы-посредники мы должны создать ДЛЯ КАЖДОГО
// метода из FileLogger
}

9
inherit/final.php Normal file
View File

@ -0,0 +1,9 @@
<?php
class Base
{
public final function test() {}
}
class Derive extends Base
{
public function test() {} // Ошибка! Нельзя переопределить!
}

6
inherit/inherit0.php Normal file
View File

@ -0,0 +1,6 @@
<?php
require_once 'file/logger/debug0.php';
$logger = new FileLoggerDebug0('test', 'test.log');
$logger->log('Обычное сообщение');
$logger->debug('Отладочное сообщение');

14
inherit/inherit0cast.php Normal file
View File

@ -0,0 +1,14 @@
<?php
require_once 'file/logger/debug0.php';
$logger = new FileLoggerDebug0('test', 'test.log');
// Казалось бы, все верно - все, что может FileLogger,
// 'умеет' и FileLoggerDebug0...
croak($logger, 'Hasta la vista.');
// Функция принимает параметр типа FileLogger
function croak(FileLogger $l, $msg) {
$l->log($msg);
exit();
}

View File

@ -0,0 +1,21 @@
<?php
class Base
{
public static function title()
{
echo __CLASS__;
}
public static function test() {
self::title();
}
}
class Child extends Base
{
public static function title()
{
echo __CLASS__;
}
}
Child::test(); // Base

75
inherit/pages/cached.php Normal file
View File

@ -0,0 +1,75 @@
<?php
require_once 'page.php';
class Cached extends Page
{
// Время действия кэша
protected $expires;
// Хранилище
protected $store;
// Конструктор класса
public function __construct($title = '', $content = '', $expires = 0)
{
// Вызываем конструктор базового класса Page
parent::__construct($title, $content);
// Устанавливаем время жизни кэша
$this->expires = $expires;
// Подготовка хранилища
// $this->store = new Memcached();
// $this->store->addServer('localhost', 11211);
// Размещение данных в хранилище
$this->set($this->id('title'), $title);
$this->set($this->id('content'), $content);
}
// Проверить, есть ли позиция $key в кэше
protected function isCached($key)
{
// return (bool) $this->store->get($key);
}
// Поместить в кэш по ключу $key значение $value.
// В случае если ключ уже существует:
// 1. Не делать ничего, если $force принимает значение false.
// 2. Переписать, если $force принимает значение true.
protected function set($key, $value, $force = false)
{
// if ($force) {
// $this->store->set($key, $value, $this->expires);
// } else {
// if($this->isCached($key)) {
// $this->store->set($key, $value, $this->expires);
// }
// }
}
// Извлечение значения $key из кэша
protected function get($key)
{
// return $this->store->get($key);
}
// Формируем уникальный ключ для хранилища
public function id($name)
{
die('Что здесь делать? Неизвестно!');
}
// Получение заголовка страницы
public function title()
{
// if ($this->isCached($this->id('title'))) {
// return $this->get($this->id('title'));
// } else {
return parent::title();
// }
}
// Получение содержимое страницы
public function content()
{
// if ($this->isCached($this->id('content'))) {
// return $this->get($this->id('content'));
// } else {
return parent::content();
// }
}
}

View File

@ -0,0 +1,18 @@
<?php
require_once 'page_a.php';
abstract class Cached extends Page
{
// Время действия кэша
protected $expires;
// Хранилище
protected $store;
...
// Формируем уникальный ключ для хранилища
abstract public function id($name);
...
}

10
inherit/pages/cast.php Normal file
View File

@ -0,0 +1,10 @@
<?php
require_once 'static_page.php';
function echoPage(Page $obj)
{
$obj->render();
}
$shape = new StaticPage(3);
echoPage($shape);

View File

@ -0,0 +1,14 @@
<?php
require_once 'static_page.php';
function echoPage($obj)
{
$class = 'Page';
if (!($obj instanceof $class)) {
die("Argument 1 must be an instance of $class.<br />");
}
$obj->render();
}
$page = new StaticPage(3);
echoPage($page);

30
inherit/pages/news.php Normal file
View File

@ -0,0 +1,30 @@
<?php
require_once 'cached.php';
class StaticPage extends Cached
{
// Конструктор класса
public function __construct($id)
{
// Проверяем, нет ли такой страницы в кэше
if ($this->isCached($this->id($id))) {
// Есть, инициализируем объект содержимым кэша
parent::__construct($this->title(), $this->content());
} else {
// Данные пока не кэшированы, извлекаем
// содержимое из базы данных
// $query = "SELECT * FROM news WHERE id = :id LIMIT 1"
// $sth = $dbh->prepare($query);
// $sth = $dbh->execute($query, [$id]);
// $page = $sth->fetch(PDO::FETCH_ASSOC);
// parent::__construct($page['title'], $page['title']);
parent::__construct('Новости', 'Содержимое страницы Новости');
}
}
// Уникальный ключ для кэша
public function id($name)
{
return "news_{$name}";
}
}

34
inherit/pages/page.php Normal file
View File

@ -0,0 +1,34 @@
<?php
class Page
{
// Любая страница имеет заголовок
protected $title;
// И содержимое
protected $content;
// Конструктор класса
public function __construct($title = '', $content = '')
{
$this->title = $title;
$this->content = $content;
}
// Получение заголовка страницы
public function title()
{
return $this->title;
}
// Получение содержимого страницы
public function content()
{
return $this->content;
}
// Формирование HTML-представления страницы
public function render()
{
echo '<h1>' . htmlspecialchars($this->title()) . '</h1>';
echo '</p>' . nl2br(htmlspecialchars($this->content())) . '</p>';
}
}

34
inherit/pages/page_a.php Normal file
View File

@ -0,0 +1,34 @@
<?php
abstract class Page
{
// Любая страница имеет заголовок
protected $title;
// И содержимое
protected $content;
// Конструктор класса
public function __construct($title = '', $content = '')
{
$this->title = $title;
$this->content = $content;
}
// Получение заголовка страницы
public function title()
{
return $this->title;
}
// Получение содержимого страницы
public function content()
{
return $this->content;
}
// Формирование HTML-представления страницы
public function render()
{
echo '<h1>' . htmlspecialchars($this->title()) . '</h1>';
echo '</p>' . nl2br(htmlspecialchars($this->content())) . '</p>';
}
}

View File

@ -0,0 +1,30 @@
<?php
require_once 'cached.php';
class StaticPage extends Cached
{
// Конструктор класса
public function __construct($id)
{
// Проверяем, нет ли такой страницы в кэше
if ($this->isCached($this->id($id))) {
// Есть, инициализируем объект содержимым кэша
parent::__construct($this->title(), $this->content());
} else {
// Данные пока не кэшированы, извлекаем
// содержимое из базы данных
// $query = "SELECT * FROM static_pages WHERE id = :id LIMIT 1"
// $sth = $dbh->prepare($query);
// $sth = $dbh->execute($query, [$id]);
// $page = $sth->fetch(PDO::FETCH_ASSOC);
// parent::__construct($page['title'], $page['title']);
parent::__construct('Контакты', 'Содержимое страницы Контакты');
}
}
// Уникальный ключ для кэша
public function id($name)
{
return "static_page_{$id}";
}
}

7
inherit/pages/test.php Normal file
View File

@ -0,0 +1,7 @@
<?php
require_once 'static_page.php';
$id = 3;
$page = new StaticPage($id);
$page->render();
echo $page->id($id);

22
inherit/static.php Normal file
View File

@ -0,0 +1,22 @@
<?php
class Base
{
public static function title()
{
echo __CLASS__;
}
public static function test()
{
static::title();
}
}
class Child extends Base
{
public static function title()
{
echo __CLASS__;
}
}
Child::test(); // Child

0
inherit/test.log Normal file
View File