Php abstract class implements interface

Абстрактные классы и интерфейсы

В индексном файле index.php (все файлы взяты из предыдущего урока » Модификаторы доступа «) в объявленную переменную $product поместим экземпляр класса Product и передадим параметры:

‘ Test ‘(имя) и 1 (цена). После обновления страницы получим:

.
.
.
Product Object
(
[name:Product:private] => Test
[price:protected] => 1
[discount:Product:private] => 0
)

— мы создали некий неопределенный (абстрактный) продукт, у которого есть наименование и цена — больше ничего нет, и быть не может и он нам не нужен. Чтобы не допустить создания таких абстрактных продуктов и существуют абстрактнае классы.

Абстрактные классы и методы

Основная задача абстрактного класса — не дать возможности создать объект (экземпляр) от этого класса .

При наследовании от абстрактного класса все методы, которые помечены абстрактными в родительском классе, должны быть обязательно определены в дочернем классе.

Если в каком-нибудь классе присутствует абстрактный метод, то такой класс, по умолчанию, должен становиться абстрактным.

Абстрактные классы создаются при помощи ключевого слова abstract , которое добавляется перед началом объявления класса: abstract class Product — тем самым мы делаем наш класс абстрактным. Теперь мы не можем создать экземпляр класса(объект), который является абстрактным.

Это логично, так как класс Product это базовый класс, который создавался нами, чтобы описать некие базовые свойста и метода, которые будут наследовать все прочие дочерние классы (BookProduct и NoteBookProduct).

Особенности использовании абстрактных классов

При наследовании от абстрактного класса все методы, которые помечены абстрактными в родительском классе, должны быть обязательно определены в дочернем классе.

В классе Product определим некий метод абстрактным ( abstract ) и защищенным ( protected ) с двумя параметрами $name , $price :

abstract protected function addProduct ( $name , $price );

— абстрактные методы не должны содержать реализацию (тело метода) .

// абстрактные классы создаются при помощи ключевого слова abstract
abstract class Product
<
private $name ;
protected $price ;
private $discount = 0 ;

public function __construct ( $name , $price )
<
$this -> name = $name ;
$this -> price = $price ;
>
public function getProduct ()
<
return «


О товаре:

Наименование: < $this ->name >

Цена со скидкой: < $this ->getPrice ()>
» ;
>

// общие гетеры:
public function getName ()
<
return $this -> name ;
>

public function getPrice ()
<
return $this -> price ( $this -> discount / 100 * $this -> price );
>

public function getDiscount ()
<
return $this -> discount ;
>

public function setDiscount ( $discount )
<
$this -> discount = $discount ;
>

// определяем некоторый метод абстрактным, защищенным еще и
// назовем его addProduct() (с двумя параметрами $name, $price)
// абстрактные методы не должны содержать реализацию (тело метода)
// в дочернем классе BookProduct мы должны этод метод — addProduct
// реализовать или хотя-бы объявить
abstract protected function addProduct ( $name , $price );
>
?>

Когда мы наследуем абстрактный класс, где есть абстрактные методы, то мы должны следить за областью видимости — она должна либо совпадать с областью видимости родительского метода, либо же быть ниже ( protected —> protected или protected —> public ).

Тоже самое касается и параметров — количество параметров должно совпадать.

Но если нам нужно, допустим, три параметра то мы можем все же их добавить — для этого мы делаем дополнительные параметры необязательными ( $numePage=0 ) и все будет работать — мы можем их распечатать:

public function addProduct ( $name , $price , $numePage = 0 )
<
// —————————
var_dump ( $name );
var_dump ( $price );
var_dump ( $numePage );
>

class BookProduct extends Product
<
public $numPages ;

public function __construct ( $name , $price , $numPages )
<
parent :: __construct ( $name , $price );
$this -> numPages = $numPages ;
$this -> setDiscount ( 5 );
>

public function getProduct ()
<
$out = parent :: getProduct ();
$out .= «Цена без скидки: < $this ->price >
» ;
$out .= «Кол-во страниц:: < $this ->cpu >
» ;
$out .= «Скидка: < $this ->getDiscount ()> %
» ;
return $out ;
>

public function getNumPeges ()
<
return $this -> numPages ;
>

// объявляем метод addProduct без реализации
// когда мы наследуем абстрактный класс, где есть абстрактные методы,
// то область видимости либо должна совпадать
// с областью видимости родительского метода, либо быть ниже (protected —> public)
// так-же количество параметров должно совпадать или дополнительные
// параметры мы делаем необязательными
public function addProduct ( $name , $price , $numePage = 0 )
<
// —————————
var_dump ( $name );
var_dump ( $price );
var_dump ( $numePage );
>
>
?>

Вызовем в индексном файле метод addProduct с параметрами: $book -> addProduct(‘Test’, 10, 5) :

error_reporting (- 1 );
require_once ‘classes/Product.php’ ;
require_once ‘classes/BookProduct.php’ ;
function debug ( $data )
<
echo ‘

' . print_r ( $data , 1 ) . '

‘ ;
>

$book = new BookProduct (‘ Три мушкетера’ , 20 , 1000 );

// в объявленную переменную $product поместим экземпляр класса Product
// и передадим параметры: ‘Test’ и 1
// мы создали некий неопределенный продукт, у которого есть наименование
// и цена (больше ничего нет, и быть не может)
// — это получается абстрактный продукт, который нам не нужен
// чтобы исключить создание таких абстрактных продуктов,
// как раз и существуют абстрактные классы
// $product = new Product(‘Test’, 1);
// debug($product);

// вызовем метод addProduct
$book -> addProduct ( ‘Test’ , 10 , 5 );

BookProduct Object
(
[numPages] => 1000
[name:Product:private] => Три мушкетера
[price:protected] => 20
[discount:Product:private] => 5
)
—————————————————————————————-
О товаре:
Наименование: Три мушкетера
Цена со скидкой: 19
Цена без скидки: 20
Кол-во страниц: 1000
Скидка: 5%

результат работы метода addProduct:
string ‘Test’ (length=4)
int 10
int 5

Интерфейсы

Интерфейсы — это по сути те же самые классы, но без реализации .

Объявляются они с помощью ключевого слова interface .

Плюс интерфейсов состоит в том, что их можно наследовать сколь угодно много. Если, например, мы можем наследовать (расширять) только один класс ( class BookProduct extends Product ), то в случае с интерфейсом мы можем наследовать, или точнее, реализовывать сколько угодно много интерфейсов (перечисляя их через запятую).

Все объявленные в интерфейсе методы должны быть публичные и не иметь реализацию, как абстрактные методы в абстрактном классе (от интерфейса нельзя создать объекта, как и от абстрактного класса).

Вся логика интерфейса — она реализуется в классе, реализующим этот самый интерфейс .

В папке classes создадим интерфейс: interface I3D ( 3D книги). Интерфейсы именуют, начиная с большой » I » или маленькой буквы » i «, а далее идет наименование интерфейса ( 3D ).

Внутри интерфейса мы можем создавать свойства, константы и методы.

Причем отличие константы интерфейса от констант обычных классов, заключается в том, что переопределять константу, которая определена в интерфейсе — мы не можем. В обычных классах мы можем переопределить (перезагрузить) константу в классах наследниках.

Для примера в классе Product создадим константу TEST и присвоим значение = 10 , в классе BookProduct создадим константу TEST и присвоим значение = 20 (как и в классе Product . =10) — константа будет преопределена.

При попытке переопределить константу TEST2 , объявленную в интерфейсе I3D — столкнемся с ошибкой.

interface I3D
<
// константа интерфейса
const TEST2 = ‘test interface’ ;

// метод интерфейса (данный метод не имеет реализацию)
public function test ();
>
?>

В классе BookProduct реализуем наш интерфейс.

Чтобы реализовать наш интерфейс просто дописываем к классу ключевое слово: implements и его название I3D.

Чтобы не было ошибки, надо метод, который есть в интерфейсе: test() , надо реализовать в классе (BookProduct), реализующим данный интерфейс (как и в случае с абстрактным классом).

// чтобы реализовать наш интерфейс просто дописываем к классу ключевое слово:
// implements и его название I3D ;
// чтобы не было ошибки, надо метод, который есть в интерфейсе: test(),
// надо реализовать в классе,
// реализующим данный интерфейс (как и в случае с абстрактным классом)
class BookProduct extends Product implements I3D
<
public $numPages ;

// создадим константу TEST и присвоим значение = 20 (как и в классе Product . =10)
// константа будет преопределена
const TEST = 20 ;

// const TEST2 = 30;
// — выведет ошибку, так как преопределять константу,
// которая определена в интерфейсе — мы не можем

public function __construct ( $name , $price , $numPages )
<
parent :: __construct ( $name , $price );
$this -> numPages = $numPages ;
$this -> setDiscount ( 5 );

var_dump ( self :: TEST );
// — выведет в браузере — 20 ; т. есть в классе BookProduct
// мы преопределили константу TEST, если её закоментировать,
// то выведет — 10 ; т. есть как и в родительском классе
>

// объявляем и реализуем метод test() из интерфейса (из файла I3D.php)
public function test ()
<
// убедимся, что всё работает
var_dump ( self :: TEST2 );
// (вызывем метод test() в индексном файле)
>

public function getProduct ()
<
$out = parent :: getProduct ();
$out .= «Цена без скидки: < $this ->price >
» ;
$out .= «Кол-во страниц:: < $this ->cpu >
» ;
$out .= «Скидка: < $this ->getDiscount ()> %
» ;
return $out ;
>

public function getNumPeges ()
<
return $this -> numPages ;
>

public function addProduct ( $name , $price , $numePage = 0 )
<
// —————————
var_dump ( $name );
var_dump ( $price );
var_dump ( $numePage );
>
>
?>

Подключаем интерфейс в индексном файле и вызывем метод test()

error_reporting (- 1 );
require_once ‘classes/Product.php’ ;
require_once ‘classes/BookProduct.php’ ;
// подключаем интерфейсный файл interface I3D
require_once ‘classes/I3D.php’ ;

function debug ( $data )
<
echo ‘

' . print_r ( $data , 1 ) . '

‘ ;
>

$book = new BookProduct ( ‘Три мушкетера’ , 20 , 1000 );

$book -> addProduct ( ‘Test’ , 10 , 5 );

// вызываем метод test() (выведет в браузере ‘test interface’ )
$book -> test ();

var_dump(self::TEST) — вывод константы из класса BookProduct :
int 20

BookProduct Object
(
[numPages] => 1000
[name:Product:private] => Три мушкетера
[price:protected] => 20
[discount:Product:private] => 5
)
—————————————————————————————-
О товаре:
Наименование: Три мушкетера
Цена со скидкой: 19
Цена без скидки: 20
Кол-во страниц: 1000
Скидка: 5%

результат работы метода addProduct:
string ‘Test’ (length=4)
int 10
int 5

string ‘test interface’ (length=14) — работа метода test()

Источник

Читайте также:  Html request header charset
Оцените статью