ООП   PHP   web   4GL - визуальные среды

Лабораторная работа ч.3 по объектно-ориентированному программированию на PHP

Это третья часть лабораторной работы по ООП. Первый две части можно найти тут: часть 1 и часть 2.

Сегодня мы продолжаем заниматься практической деятельностью по освоению объектно-ориентированного программирования. И давайте начнем наш сегодняшний урок с такого понятия, как полиморфизм или по-другому — наследование.

Итак, что же такое полиморфизм?

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

Например, у меня есть класс Car со свойством, которое называется «год выпуска» ($year) и методом, который выводит скорость автомобиля и называется он — function paintSpeed():

<?php
class Car{
//свойства
public $year = 2003;
//метод
function paintSpeed(){
	echo "Скорость автомобиля = ".$this->speed;
    }
}
?>

На основе этого класса, я могу создать класс, например, класс Opel, который будет иметь такое же свойство и такой же метод, как мой класс Car. Теперь класс Car является родителем для класса Opel.

Так как же создается наследование?

Класс наследник или наследование (полиморфизм) создается с помощью ключевого слова extends.

Давайте посмотрим на примере:

<?php
//это класс родитель
class Car{
	//свойства
	public $year = 2003;
	
	//метод
	function paintSpeed(){
//указываем методу, чью скорость мы хотим получить. Идет обращение из метода к свойству
		echo "Скорость автомобиля = ".$this->speed;
	}
}

//это класс наследник, который имеет свойство $year и метод paintSpeed()
class Opel extends Car{
	//свойство
	public $model;
}
?>

Еще раз:

Когда мы создаем класс наследник, используя ключевое слово extends, то он автоматически наследует все свойства и методы класса родителя. В самом классе-наследнике мы не увидим этих свойств и методов, однако они там есть и к ним можно будет обращаться. Как именно это делать, я покажу далее.

Однако и сам класс наследник наряду со свойствами и методами класса родителя может иметь так же и свои свойства и методы.

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

Теперь давайте посмотрим, как мы можем обращаться из класса наследника к его собственным свойствам и методам, так и к унаследованным:

<?php
//это класс родитель
class Car{
	//свойства
	public $year = 2003;
	
	//метод
	function paintSpeed(){
//указываем методу, чью скорость мы хотим получить. Идет обращение из метода к свойству
		echo "Скорость автомобиля = ".$this->speed;
	}
}

//это класс наследник, который имеет свойство $year и метод paintSpeed()
class Opel extends Car{
	//свойство
	public $model;
}

$myCar = new Opel();
//обращение к свойству класса родителя
$myCar->$year;
//обращение к собственному свойству 
$myCar->$model;
?>

Соответственно из класса Opel мы тоже можем создать класс наследник.

Теперь давайте вернемся к нашей лабораторной работе.

Задание у нас будет следующее:

  1. Описать класс SuperUsers унаследованный от класса Users;
  2. В классе SuperUsers описать свойство character и создать объект, экземпляр класса SuperUsers;
  3. Задать значение свойству character = «admin»;
  4. Вызвать метод getInfo() для созданного объекта;
  5. Отдельно от метода getInfo() вывести значение свойства character;

Вот что у нас должно было получиться:

<?php
class Users{
	public $name;
	public $login;
	public $password;
	
	//создание конструктора
	function __construct($name, $login, $password){
		$this->name = $name;
		$this->login = $login;
		$this->password = $password;
	}
	
	//создаем метод clone
	function __clone(){
		$this->name = "User";
		$this->login = "User";
		$this->password = "qwerty";
	}
	
	//создаем методод getInfo()
	function getInfo(){
		echo "<p>Name: ".$this->name."<br>";
		echo "Login: ".$this->login."<br>";
		echo "Password: ".$this->password."<br>";
	}
}

$user1 = new Users("Vasya", "vas", "123");
	//выводим метод getInfo()
	$user1->getInfo();

$user2 = new Users("Petya", "pet", "321");
	//выводим метод getInfo()
	$user2->getInfo();

$user3 = new Users("Vova", "vov", "456");
	//выводим метод getInfo()
	$user3->getInfo();
//объект $user4 копия объекта $user3 
$user4 = clone $user3;
	$user4->getInfo();
	
	
	
	
//Создаем класс наследник от класса Users
class SuperUsers extends Users{
	//создаем свойство character
	public $character;
}
//создаем объект экземпляр класса SuperUsers
$user = new SuperUsers("SuperAdmin", "root", "admin1234");
//задаем значение свойству character = admin
$user->character = "admin";
//вызываем метод getInfo() для созданного объекта
$user->getInfo();
//выводим значение свойства character
echo $user->character;
?>

Запустив этот код вы увидите, что у нас появился новый пользователь SuperAdmin, который обладает такими же свойствами и методами, что и пользователи класса Users + он имеет собственное свойство-характеристику (character) — админ.

Друзья, обратите внимание, что когда мы только что создали объект класса SuperUsers, он также унаследовал и конструктор своего родителя Users. Конструктор родителя, как мы знаем может принимать три параметра ($name, $login, $password). А в классе наследнике у нас появляется четвертый параметр character, который мы прописали отдельно.

Вот тут мы с вами подходим к такому понятию, как перегрузка методов.

Что же это такое? Например, у нас есть класс родитель и класс наследник. В классе родителе описан метод getPrint() и в классе наследнике мы тоже описываем метод getPrint(), хотя он уже там есть, так как унаследован от класса родителя. Но описываем мы его немного с другими параметрами, которые нам нужны именно в классе наследнике. Так вот, при вызове метода из экземпляра класса будет вызван именно метод из класса наследника, то есть переписанный.

Знаю, немного запутанно получилось, поэтому давайте посмотрим на примере:

<?php
class Car{
	//свойство
	public $model = "Mazda";
	
	//метод
	function getPrint(){
		echo $this->model;
	}
}

//создаем класс наследник
class Infinity extends Car{
	//свойство
	public $country = "Japan";
	
	//метод, который мы перегружаем, то есть переписываем его с нужными нам здесь параметрами
	function getPrint(){
		echo "Перегруженный метод getPrint()";
	}
}

//создаем экземпляр класса Infinity
$myCar = new Infinity();
//вызываем метод getPrint()
$myCar->getPrint();//ВАЖНО! Будет вызван перегруженный метод из класса наследника Infinity
?>

Запустив этот код у нас выведется надпись — «Перегруженный метод getPrint()», а не слово «Mazda». Попробуйте в классе наследнике убрать перегруженный метод и вы увидите, что будет происходить обращение к обычному методу getPrint(), унаследованному от родителя и в этом случае выведется надпись «Mazda». Другими словами перегруженный метод у наследника как бы перекрывает родительский.

В связи с этим давайте выполним задание лабораторной работы. А именно:

  1. описать конструктор класса SuperUsers, который будет задавать начальные значения свойств;
  2. в классе SuperUsers описать метод getInfo(), который будет выводить значения этих свойств;
  3. создать заново объект класса SuperUsers и вызвать метод getInfo();

И вот что у вас должно получиться:

<?php
class Users{
	public $name;
	public $login;
	public $password;
	
	//создание конструктора
	function __construct($name, $login, $password){
		$this->name = $name;
		$this->login = $login;
		$this->password = $password;
	}
	
	//создаем метод clone
	function __clone(){
		$this->name = "User";
		$this->login = "User";
		$this->password = "qwerty";
	}
	
	//создаем методод getInfo()
	function getInfo(){
		echo "<p>Name: ".$this->name."<br>";
		echo "Login: ".$this->login."<br>";
		echo "Password: ".$this->password."<br>";
	}
}

$user1 = new Users("Vasya", "vas", "123");
	//выводим метод getInfo()
	$user1->getInfo();

$user2 = new Users("Petya", "pet", "321");
	//выводим метод getInfo()
	$user2->getInfo();

$user3 = new Users("Vova", "vov", "456");
	//выводим метод getInfo()
	$user3->getInfo();
//объект $user4 копия объекта $user3 
$user4 = clone $user3;
	$user4->getInfo();
	
	
	
	
//Создаем класс наследник от класса Users
class SuperUsers extends Users{
	//создаем свойство character
	public $character;
	//описываем конструктор для SuperUsers
	function __construct($name, $login, $password, $character){
		$this->name = $name;
		$this->login = $login;
		$this->password = $password;
		$this->character = $character;
	}
	//перегружаем метод getInfo
	function getInfo(){
		echo "<p>Name: ".$this->name."<br>";
		echo "Login: ".$this->login."<br>";
		echo "Password: ".$this->password."<br>";
		echo "Character: ".$this->character."<br>";
	}
}
//создаем объект экземпляр класса SuperUsers
$user = new SuperUsers("SuperAdmin", "root", "admin1234", "admin");
//вызываем метод getInfo() для созданного объекта
$user->getInfo();
?>

Однако, если мы посмотрим на наш код, то мы можем сказать, что здесь что-то не так. Мы говорили о том, что вся прелесть наследования заключается в том, что мы все забираем у класса родителя, а тут нам пришлось все переписать практически заново. В итоге у нас произошло увеличение кода, что в идеале не есть хорошо. А если предположить, что у нас от класса SuperUsers будет наследоваться еще один класс SuperPuperUser, а от него еще какой нибудь, то количество строк кода будет возрастать до неимоверных пределов. Поэтому с этим надо что-то делать.

Допустим, мы в данном случае перегрузили родительский метод. Поэтому метод родителя нам уже не доступен. А что если я хочу иметь возможность обратиться и к родительскому методу и перегруженному?

Для этих целей у нас существует замечательная конструкция — parent.

Записывается она так — parent->двойное двоеточие->имя метода.

parent::имя метода

Эта конструкция позволяет обратиться к родительскому методу. Суть его работы заключается в том, что когда мы перегружаем родительский метод в классе наследнике, нам уже не надо еще раз описывать метод родителя. Мы просто в перегруженном методе обращаемся к методу родителя посредством конструкции parent, а если у нас есть дополнения к методу, то указываем их ниже этой конструкции:

<?php
//Создаем класс наследник от класса Users
class SuperUsers extends Users{
	//создаем свойство character
	public $character;
	//описываем конструктор для SuperUsers
	function __construct($name, $login, $password, $character){
		//ОБРАЩАЕМСЯ К МЕТОДУ (КОНСТРУКТОРУ) РОДИТЕЛЯ ПОСРЕДСТВОМ PARENT
		parent::__construct($name, $login, $password);
		//+ у нас дополнительное свойство character, которое указываем ниже parent и не забываем также указать его в параметрах перегруженного метода
		$this->character = $character;
	}
	//перегружаем метод getInfo
	function getInfo(){
		//то же самое - обращаемся к родительскому методу getInfo()
		parent::getInfo();
		//+ дополнительное свойство
		echo "Character: ".$this->character."<br>";
	}
}
//создаем объект экземпляр класса SuperUsers
$user = new SuperUsers("SuperAdmin", "root", "admin1234", "admin");
//вызываем метод getInfo() для созданного объекта
$user->getInfo();
?>

Вот и все. В результате у нас ничего не измениться, за исключением того, что мы немного сократили количество кода.

Евгений Владимирович Андреев

ООП   PHP   web   4GL - визуальные среды

Знаете ли Вы, что "тёмная материя" - такая же фикция, как черная кошка в темной комнате. Это не физическая реальность, но фокус, подмена.
Реально идет речь о том, что релятивистские формулы не соответствуют астрономическим наблюдениям, давая на порядок и более меньшую массу и меньшую энергию. Отсюда сделан фокуснический вывод, что есть "темная материя" и "темная энергия", но не вывод, что релятивистские формулы не соответствуют реалиям. Подробнее читайте в FAQ по эфирной физике.

НОВОСТИ ФОРУМАФорум Рыцари теории эфира
Рыцари теории эфира
 15.11.2019 - 09:04: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> Проблема государственного терроризма - Карим_Хайдаров.
15.11.2019 - 06:48: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Марины Мелиховой - Карим_Хайдаров.
15.11.2019 - 06:45: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> РАСЧЕЛОВЕЧИВАНИЕ ЧЕЛОВЕКА. КОМУ ЭТО НАДО? - Карим_Хайдаров.
14.11.2019 - 12:35: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Светланы Вислобоковой - Карим_Хайдаров.
13.11.2019 - 19:20: ЭКОНОМИКА И ФИНАНСЫ - Economy and Finances -> ПРОБЛЕМА КРИМИНАЛИЗАЦИИ ЭКОНОМИКИ - Карим_Хайдаров.
12.11.2019 - 11:53: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Бориса Сергеевича Миронова - Карим_Хайдаров.
12.11.2019 - 11:49: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Веры Лесиной - Карим_Хайдаров.
11.11.2019 - 00:24: СОВЕСТЬ - Conscience -> РУССКИЙ МИР - Карим_Хайдаров.
10.11.2019 - 23:14: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Кирилла Мямлина - Карим_Хайдаров.
08.11.2019 - 06:42: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Вячеслава Осиевского - Карим_Хайдаров.
05.11.2019 - 21:56: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Декларация Академической Свободы - Карим_Хайдаров.
04.11.2019 - 12:41: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> КОМПЬЮТЕРНО-СЕТЕВАЯ БЕЗОПАСНОСТЬ ДЛЯ ВСЕХ - Карим_Хайдаров.
Bourabai Research Institution home page

Bourabai Research - Технологии XXI века Bourabai Research Institution