ООП   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 - визуальные среды

Знаете ли Вы, что релятивистское объяснение феномену CMB (космическому микроволновому излучению) придумал человек выдающейся фантазии Иосиф Шкловский (помните книжку миллионного тиража "Вселенная, жизнь, разум"?). Он выдвинул совершенно абсурдную идею, заключавшуюся в том, что это есть "реликтовое" излучение, оставшееся после "Большого Взрыва", то есть от момента "рождения" Вселенной. Хотя из простой логики следует, что Вселенная есть всё, а значит, у нее нет ни начала, ни конца... Подробнее читайте в FAQ по эфирной физике.

НОВОСТИ ФОРУМАФорум Рыцари теории эфира
Рыцари теории эфира
 21.09.2019 - 11:41: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Галины Царёвой - Карим_Хайдаров.
21.09.2019 - 11:36: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> Проблема государственного терроризма - Карим_Хайдаров.
20.09.2019 - 19:50: ЭКОНОМИКА И ФИНАНСЫ - Economy and Finances -> ПРОБЛЕМА КРИМИНАЛИЗАЦИИ ЭКОНОМИКИ - Карим_Хайдаров.
20.09.2019 - 04:36: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Вячеслава Осиевского - Карим_Хайдаров.
18.09.2019 - 12:08: НОВЫЕ ТЕХНОЛОГИИ - New Technologies -> ПРОБЛЕМА ИСКУССТВЕННОГО ИНТЕЛЛЕКТА - Карим_Хайдаров.
18.09.2019 - 06:01: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Л.Г. Ивашова - Карим_Хайдаров.
17.09.2019 - 05:51: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> ФАЛЬСИФИКАЦИЯ ИСТОРИИ - Карим_Хайдаров.
17.09.2019 - 05:41: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Андрея Тиртхи - Карим_Хайдаров.
16.09.2019 - 03:11: СОВЕСТЬ - Conscience -> РУССКИЙ МИР - Карим_Хайдаров.
14.09.2019 - 18:23: ПЕРСОНАЛИИ - Personalias -> WHO IS WHO - КТО ЕСТЬ КТО - Карим_Хайдаров.
13.09.2019 - 09:08: ЭКОЛОГИЯ - Ecology -> Биологическая безопасность населения - Карим_Хайдаров.
12.09.2019 - 17:47: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> РАСЧЕЛОВЕЧИВАНИЕ ЧЕЛОВЕКА. КОМУ ЭТО НАДО? - Карим_Хайдаров.
Bourabai Research Institution home page

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