Php this in abstract class

Абстрактные классы в PHP

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

Что такое абстрактные классы и методы в PHP?

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

Объявление абстрактных классов

Чтобы объявить абстрактный класс, нам нужно использовать ключевое слово abstract перед именем класса:

Синтаксис

Объявление абстрактных методов

Когда вы добавляете ключевое слово abstract к объявлению метода, он становится абстрактным методом. И помните, абстрактные методы не имеют тела. Поэтому фигурные скобки <> не используются.

Пример

Правила абстракции

Когда дочерний класс наследуется от абстрактного класса, применяются следующие правила:

  • Дочерний класс должен переопределить (повторно объявить) все абстрактные методы.
  • Количество обязательных аргументов для методов должны быть таким же, как у абстрактного метода. Например, в приведенном выше примере myMethod2 имеет два аргумента: $name и $age . У метода myMethod2 в дочернем классе должны быть те же аргументы:

public function myMethod2($name, $age)
public function myMethod2($name, $age, $country = ‘Germany’)
public function myMethod3() : int

Видимость абстрактного метода Видимость дочернего метода
public public
protected protected или public, но не private

Не абстрактные методы в абстрактном классе

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

Любой класс даже с одним абстрактным методом должен быть объявлен абстрактным. Но абстрактный класс также может иметь неабстрактные методы, к которым дочерние классы могут обращаться и использовать их напрямую, не переопределяя их.

Давайте расширим приведенный выше пример и включим в наш класс неабстрактный метод myMethod2:

Пример

Примечание: В этом основное отличие абстрактных классов от интерфейсов. Абстрактные классы могут иметь реальные методы, а интерфейсы могут иметь только объявления методов.

Пример абстрактного класса в PHP ООП

Родительский абстрактный класс:

Пример

 name = $name; > abstract public function greet() : string; > ?>

В родительском классе объявлены метод __construct и свойство $name . Итак, дочерний класс автоматически получит их. Но greet() — это абстрактный метод, который должен быть определен во всех дочерних классах, и они должны возвращать строку.

Как создать дочерние классы из абстрактного класса?

Поскольку мы не можем создавать объекты из абстрактных классов, нам необходимо создать дочерние классы, которые наследуют код абстрактного класса. Дочерние классы абстрактных классов формируются с помощью ключевого слова extends , как и любой другой дочерний класс. Они отличаются тем, что им нужно добавлять тела к абстрактным методам.

Примечание: Дочерние классы, которые наследуются от абстрактных классов, должны добавлять тела к абстрактным методам.

Давайте создадим дочерние классы и определим в них абстрактный метод, унаследованный от родителя, greet():

Пример

 name; > > class Student extends Person < public function greet() : string < return "Привествую! Я - " . $this ->name; > > class Teacher extends Person < public function greet() :string < return "Здравствуйте, студенты! Я - " . $this ->name; > > ?>

Теперь мы можем создавать объекты из дочерних классов:

Пример

 greet(); $student = new Student('Анна'); echo $student -> greet(); $teacher = new Teacher('Мария Ивановна'); echo $teacher -> greet(); ?>

Полный код рассмотренного примера абстрактного класса:

Пример

 name = $name; > abstract public function greet() : string; > class Programmer extends Person < public function greet() : string < return "Привет Мир! Я - " . $this ->name; > > class Student extends Person < public function greet() : string < return "Привествую! Я - " . $this ->name; > > class Teacher extends Person < public function greet() :string < return "Здравствуйте, студенты! Я - " . $this ->name; > > $programmer = new Programmer('Антон'); echo $programmer -> greet(); echo "
"; $student = new Student('Анна'); echo $student -> greet(); echo "
"; $teacher = new Teacher('Мария Ивановна'); echo $teacher -> greet(); ?>

Результат выполнения кода:

Заключение

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

Источник

Абстрактные классы в ООП на PHP

Пусть у вас есть класс User , а от него наследуют классы Employee и Student .

При этом предполагается, что вы будете создавать объекты классов Employee и Student , но объекты класса User — не будете, так как этот класс используется только для группировки общих свойств и методов своих наследников.

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

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

Для того, чтобы объявить класс абстрактным, нужно при его объявлении написать ключевое слово abstract :

Итак, давайте напишем реализацию абстрактного класса User . Пусть у него будет приватное свойство name , а также геттеры и сеттеры для него:

Попытка создать объект класса User вызовет ошибку:

А вот унаследовать от нашего класса будет можно. Сделаем класс Employee , который будет наследовать от нашего абстрактного класса User :

Создадим объект класса Employee — все будет работать:

setName(‘john’); // метод родителя, т.е. класса User $employee->setSalary(1000); // свой метод, т.е. класса Employee echo $employee->getName(); // выведет ‘john’ echo $employee->getSalary(); // выведет 1000 ?>

Аналогично можно создать объект класса Student , наследующий от User :

Самостоятельно, не подсматривая в мой код, реализуйте такой же абстрактный класс User , а также классы Employee и Student , наследующие от него.

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

Абстрактные классы также могут содержать абстрактные методы. Такие методы не должны иметь реализации, а нужны для того, чтобы указать, что такие методы должны быть у потомков. А собственно реализация таких методов — уже задача потомков.

Для того, чтобы объявить метод абстрактным, при его объявлении следует написать ключевое слово abstract .

Давайте попробуем на практике. Пусть предполагается, что все потомки класса User должны иметь метод increaseRevenue ( увеличить доход ).

Этот метод должен брать текущий доход пользователя и увеличивать его на некоторую величину, переданную параметром.

Сам класс User не знает, какой именно доход будет получать наследник — ведь у работника это зарплата, а у студента — стипендия. Поэтому каждый потомок будет реализовывать этот метод по-своему.

Фишка тут в том, что абстрактный метод класса User заставляет программиста реализовывать этот метод в потомках, иначе PHP выдаст ошибку. Таким образом вы, или другой программист, работающий с вашим кодом, никак не сможете забыть реализовать нужный метод в потомке.

Итак, давайте попробуем на практике. Добавим абстрактный метод increaseRevenue в класс User :

name; > public function setName($name) < $this->name = $name; > // Абстрактный метод без тела: abstract public function increaseRevenue($value); > ?>

Пусть наш класс Employee пока останется без изменений. В этом случае, даже если не создавать объект класса Employee , а просто запустить код, в котором определяются наши классы, — PHP выдаст ошибку.

Давайте теперь напишем реализацию метода increaseRevenue в классе Employee :

salary; > public function setSalary($salary) < $this->salary = $salary; > // Напишем реализацию метода: public function increaseRevenue($value) < $this->salary = $this->salary + $value; > > ?>

Проверим работу нашего класса:

setName(‘john’); // установим имя $employee->setSalary(1000); // установим зарплату $employee->increaseRevenue(100); // увеличим зарплату echo $employee->getSalary(); // выведет 1100 ?>

Реализуем метод increaseRevenue и в классе Student . Только теперь наш метод будет увеличивать уже стипендию:

scholarship; > public function setScholarship($scholarship) < $this->scholarship = $scholarship; > // Метод увеличивает стипендию: public function increaseRevenue($value) < $this->scholarship = $this->scholarship + $value; > > ?>

Добавьте в ваш класс User такой же абстрактный метод increaseRevenue . Напишите реализацию этого метода в классах Employee и Student .

Добавьте также в ваш класс User абстрактный метод decreaseRevenue ( уменьшить зарплату ). Напишите реализацию этого метода в классах Employee и Student .

Некоторые замечания

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

При этом область видимости этих методов должна совпадать или быть менее строгой. Что значит менее строгой: например, если абстрактный метод объявлен как protected , то реализация этого метода должна быть protected или public , но не private .

Объявления методов также должны совпадать: количество обязательных параметром должно быть одинаковым. Однако класс-потомок может добавлять необязательные параметры, которые не были указаны при объявлении метода в родителе.

Практика

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

Давайте сделаем для этого абстрактный класс Figure с двумя абстрактными методами getSquare и getPerimeter .

Почему класс Figure абстрактный: потому что он не описывает реально существующую геометрическую фигуру и, соответственно, объект этого класса мы не будем создавать.

Почему методы getSquare и getPerimeter абстрактные: потому что каждая фигура имеет свой алгоритм вычисления площади и периметра и, соответственно, класс Figure не может написать реализацию этих методов.

Зачем нам вообще нужен класс Figure : чтобы наследовать от него и таким образом заставить всех наследников реализовать указанные методы.

Итак, напишем реализацию класса Figure :

Пусть теперь мы хотим создать класс Quadrate для описания геометрической фигуры квадрат. Как известно, у квадрата все стороны равны, поэтому для описания квадрата нам нужно задать только его ширину.

Давайте для этого сделаем приватное свойство $a , значение которого будет задаваться в конструкторе класса:

Давайте теперь унаследуем наш класс Quadrate от класса Figure :

a = $a; > > /* Код класса не рабочий и будет выдавать ошибку, так как мы не написали реализацию методов родителя. */ ?>

Сейчас наша реализация класса Quadrate не рабочая, так как мы не написали реализацию абстрактных методов родителя.

Давайте создадим квадрат со стороной 2 и найдем его площадь и периметр:

Сделайте аналогичный класс Rectangle ( прямоугольник ), у которого будет два приватных свойства: $a для ширины и $b для длины. Данный класс также должен наследовать от класса Figure и реализовывать его методы.

Усложним

Сейчас все методы класса Figure — абстрактные. Это, конечно же, не обязательно. Пусть наш класс имеет еще и метод getRatio , который будет находить отношение площади к периметру (то есть одно делить на второе).

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

Почему мы можем написать реализацию этого метода прямо в классе Figure : потому что этот метод будет одинаковым для всех потомков.

Обратите внимание на следующее: хотя методы getSquare и getPerimeter абстрактные и не имеют реализации, мы их все равно можем использовать в своем методе getRatio , хотя реализация этих методов появится только в потомках.

getSquare(); // выведет 4 echo $quadrate->getPerimeter(); // выведет 8 echo $quadrate->getRatio(); // выведет 0.5 ?>

Добавьте в класс Figure метод getSquarePerimeterSum , который будет находить сумму площади и периметра.

Источник

Читайте также:  Php удаление выбранной строки
Оцените статью