mirror of
https://github.com/igorsimdyanov/php8.git
synced 2025-07-29 12:52:43 +00:00
Глава 30: наследование (черновик)
This commit is contained in:
15
inherit/anonym.php
Normal file
15
inherit/anonym.php
Normal 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
26
inherit/anonym_nested.php
Normal 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
27
inherit/file/logger.php
Normal 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;
|
||||
}
|
||||
}
|
31
inherit/file/logger/debug.php
Normal file
31
inherit/file/logger/debug.php
Normal 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");
|
||||
}
|
||||
|
||||
// Все остальные методы и свойства наследуются автоматически!
|
||||
}
|
32
inherit/file/logger/debug0.php
Normal file
32
inherit/file/logger/debug0.php
Normal 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
9
inherit/final.php
Normal 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
6
inherit/inherit0.php
Normal 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
14
inherit/inherit0cast.php
Normal 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();
|
||||
}
|
21
inherit/inherit_static.php
Normal file
21
inherit/inherit_static.php
Normal 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
75
inherit/pages/cached.php
Normal 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();
|
||||
// }
|
||||
}
|
||||
}
|
18
inherit/pages/cached_a.php
Normal file
18
inherit/pages/cached_a.php
Normal 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
10
inherit/pages/cast.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
require_once 'static_page.php';
|
||||
|
||||
function echoPage(Page $obj)
|
||||
{
|
||||
$obj->render();
|
||||
}
|
||||
|
||||
$shape = new StaticPage(3);
|
||||
echoPage($shape);
|
14
inherit/pages/instanceof.php
Normal file
14
inherit/pages/instanceof.php
Normal 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
30
inherit/pages/news.php
Normal 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
34
inherit/pages/page.php
Normal 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
34
inherit/pages/page_a.php
Normal 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>';
|
||||
}
|
||||
}
|
30
inherit/pages/static_page.php
Normal file
30
inherit/pages/static_page.php
Normal 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
7
inherit/pages/test.php
Normal 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
22
inherit/static.php
Normal 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
0
inherit/test.log
Normal file
Reference in New Issue
Block a user