Пятница, 19.04.2024, 21:46
Приветствую Вас Гость

Объектно-ориентированное программирование

Меню сайта
Категории раздела
Наш опрос
Оцените мой сайт
Всего ответов: 2
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Главная » Статьи » 4. Лабораторные работы » Лабораторная работа ч.3 по объектно-ориентированному программированию на PHP

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

Лабораторная работа ч.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();
?>

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

Категория: Лабораторная работа ч.3 по объектно-ориентированному программированию на PHP | Добавил: Efes16rus (25.01.2015)
Просмотров: 571 | Рейтинг: 0.0/0
Всего комментариев: 0
avatar
Вход на сайт
Поиск
Друзья сайта