Php get extending class

Php get extending class

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

Чтобы наследовать один класс от другого, нам надо применить оператор extends . Стоит отметить, что в PHP мы можем унаследовать класс только от одного класса. Множественное наследование не поддерживается.

Например, унаследуем класс Employee от класса Person :

name = $name; > function displayInfo() < echo "Имя: $this->name
"; > > class Employee extends Person <> $tom = new Employee("Tom"); $tom -> displayInfo(); ?>

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

И так как класс Employee унаследован от Person, для объектов класса Employee мы можем использовать функционал родительского класса Person. Так, для создания объекта Employee в данном случае вызывается конструктор, который определен в классе Person и который в качестве параметра принимает имя человека:

Читайте также:  Python convert bytes to megabytes

И также у переменной типа Employee вызывается метод displayInfo , который определен в классе Person:

Переопределение функционала

Унаследовав функционал от родительского класса класс-наследник может добавить свои свойства и методы или переопредилить унаследованный функционал. Например, изменим класс Employee, добавив в него данные о компании, где работает работник:

name = $name; > function displayInfo() < echo "Имя: $this->name
"; > > class Employee extends Person < public $company; function __construct($name, $company) < $this->name = $name; $this->company = $company; > function displayInfo() < echo "Имя: $this->name
"; echo "Работает в $this->company
"; > > $tom = new Employee("Tom", "Microsoft"); $tom -> displayInfo(); ?>

Здесь класс Employee добавляет новое свойство — $company , которое хранит компанию работника. Также класс Employee переопределил конструктор, в который пеередаются данные для имени и компании. А также переопределен метод displayInfo() . Соответственно для создания объекта класса Employee, теперь необходимо использовать переопределенный в классе Employee конструктор:

$tom = new Employee("Tom", "Microsoft");

Класс-наследник переопределяет конструктор родительского класса, то для создания объекта класса-наследника необходимо использовать переопределенный в нем конструктор.

И также изменится поведение метода displayInfo() , который кроме имени также выведет и компанию работника:

Имя: Tom Работает в Microsoft

Вызов функционала родительского класса

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

Также вывод имени работника в методе displayInfo() :

В обоих случаях речь идет об одной строке кода. Однако что, если конструктор Employee повторяет установку не одного, а десятка свойств. Соответственно что, если метод displayInfo в классе-наследнике повторяет горадо больше действий родительского класса. В этом случае горадо рациональнее не писать повторяющийся код в классе-наследнике, а вызвать в нем соответствующий функционал родительского класса.

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

Например, перепишем предыдущий пример:

name = $name; > function displayInfo() < echo "Имя: $this->name
"; > > class Employee extends Person < public $company; function __construct($name, $company) < parent::__construct($name); $this->company = $company; > function displayInfo() < parent::displayInfo(); echo "Работает в $this->company
"; > > $tom = new Employee("Tom", "Microsoft"); $tom -> displayInfo(); ?>

Теперь в конструкторе Employee вызывается конструктор базового класса:

В нем собственно и происходит установка имени. И подобным образом в методе displayInfo() вызывается реализация метода класса Person:

В итоге мы получим тот же самый результат.

Стоит отметить, что в реальности ключевое слово parent заменяет название класса. То есть мы также могли вызывать функционал родительского класса через имя этого класса:

class Employee extends Person < public $company; function __construct($name, $company) < Person::__construct($name); $this->company = $company; > function displayInfo() < Person::displayInfo(); echo "Работает в $this->company
"; > >

Оператор instanceof

Оператор instanceof позволяет проверить принадлежность объекта определенному класса. Слева от оператора располагается объект, котоый надо проверить, а справа — название класса. И если объект представляет класс, то оператор возвращает true . Например:

class Person < public $name; function __construct($name) < $this->name = $name; > function displayInfo() < echo "Имя: $this->name
"; > > class Employee extends Person < public $company; function __construct($name, $company) < Person::__construct($name); $this->company = $company; > function displayInfo() < Person::displayInfo(); echo "Работает в $this->company
"; > > class Manager<> $tom = new Employee("Tom", "Microsoft"); $tom instanceof Employee; // true $tom instanceof Person; // true $tom instanceof Manager; // false

Здесь переменная $tom представляет класс Employee , поэтому $tom instanceof Employee возвращает true .

Так как класс Employee унаследован от Person, то переменная $tom также представляет класс Person (работник также является человеком).

А вот класс Manager переменная $tom не преддставляет, поэтому выражение $tom instanceof Manager возвращает false .

Запрет наследования и оператор final

В примере выше метод displayInfo() переопределялся классом-наследником. Однако иногда возникают ситуации, когда надо запретить переопределение методов. Для этого в классе-родителе надо указать методы с модификатором final :

class Person < public $name; function __construct($name) < $this->name = $name; > final function displayInfo() < echo "Имя: $this->name
"; > > class Employee extends Person < public $company; function __construct($name, $company) < Person::__construct($name); $this->company = $company; > function displayEmployeeInfo() < Person::displayInfo(); echo "Работает в $this->company
"; > > $tom = new Employee("Tom", "Microsoft"); $tom -> displayEmployeeInfo();

В этом случае во всех классах-наследниках от класса Person мы уже не сможем определить метод с таким же именем. Поэтому в данном случае в классе Employee определен новый метод — displayEmployeeInfo.

Также мы можем вообще запретить наследование от класса. Для этого данный класс надо определить с модификатором final :

final class Person < public $name; function __construct($name) < $this->name = $name; > final function displayInfo() < echo "Имя: $this->name
"; > >

Теперь мы не сможем унаследовать класс Employee (да и никакой другой класс) от класса Person.

Источник

Is it possible to get the name of class/file which extends another class in PHP?

In this example I want to have a line in classC which does the following pseudo code:

if (extended by classA) else if (extended by classB) 

Seeing as this is closed, I can’t post an answer. You are looking for this however: php.net/manual/en/function.is-subclass-of.php

2 Answers 2

BUT: This is a horrible design. A parent should not know about its children and specialise its behaviour depending on who extends it. It needs to be the other way around. The parent provides some functionality and the children each use it as necessary. Turn it around and only call a parent function from a specific child, and don’t call it from other children:

class MyController < public function foo() < .. >> class ClassB extends MyController < public function __construct() < $this->foo(); > > class ClassD extends MyController < public function __construct() < // simply don't call >> 

PHP has a function that will check if a class is a subclass of another.

The following is taken from the docs:

 // define a child class class WidgetFactory_Child extends WidgetFactory < var $oink = 'oink'; >// create a new object $WF = new WidgetFactory(); $WFC = new WidgetFactory_Child(); if (is_subclass_of($WFC, 'WidgetFactory')) < echo "yes, \$WFC is a subclass of WidgetFactory\n"; >else < echo "no, \$WFC is not a subclass of WidgetFactory\n"; >if (is_subclass_of($WF, 'WidgetFactory')) < echo "yes, \$WF is a subclass of WidgetFactory\n"; >else < echo "no, \$WF is not a subclass of WidgetFactory\n"; >// usable only since PHP 5.0.3 if (is_subclass_of('WidgetFactory_Child', 'WidgetFactory')) < echo "yes, WidgetFactory_Child is a subclass of WidgetFactory\n"; >else < echo "no, WidgetFactory_Child is not a subclass of WidgetFactory\n"; >?> 
yes, $WFC is a subclass of WidgetFactory no, $WF is not a subclass of WidgetFactory yes, WidgetFactory_Child is a subclass of WidgetFactory 

On another page there is a user-contributed note that has a function that gets the children (if you want to go the other way at some point):

 $t = $p; > return false; > abstract class A < function someFunction() < return get_child($this, __CLASS__); >> class B extends A < >class C extends B < >$c = new C(); echo $c->someFunction(); //displays B ?> 

Источник

how to obtain all subclasses of a class in php

You mean like «hey, PHP, what subclasses are out there for class MyBaseClass»? Probably not, because they may live in files that aren’t loaded.

3 Answers 3

function getSubclassesOf($parent) < $result = array(); foreach (get_declared_classes() as $class) < if (is_subclass_of($class, $parent)) $result[] = $class; >return $result; > 

Coincidentally, this implementation is exactly the one given in the question linked to by Vadim.

Yes, it’s just necessary to keep in mind it will only work if the files defining these classes are already (auto)loaded. Great code though.

$children = array_filter(get_declared_classes(), fn($class) => is_subclass_of($class, MyClass::class)); 
function getClassNames(string $className): array < $ref = new ReflectionClass($className); $parentRef = $ref->getParentClass(); return array_unique(array_merge( [$className], $ref->getInterfaceNames(), $ref->getTraitNames(), $parentRef ?getClassNames($parentRef->getName()) : [] )); > 

This question is in a collective: a subcommunity defined by tags with relevant content and experts.

Linked

Hot Network Questions

Subscribe to RSS

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.7.27.43548

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.

Источник

php — list of all classes that extends a given class

I am building a little cms and I would like to know which is the best way to preceed. Suppose I have classes myClassA , myClassB , myClassC , . that extend a given class myClass . I need a function to list all the classes MyClass* that extend MyClass . Is there a simple and safe way to do this just with PHP, or should I mantain the list somewhere else (maybe a table in the database)? I hope the question is clear enough.

I would read the contents of the file using file_get_contents(), then split the words using explode() exploding by a [space]. I would then use a regex expression ‘~MyClass[A-Za-z0-9]~’ (or other applicable expression) using preg_match() and store all matches in an array. I would finally filter these by using array_filter() to get a unique list you can use however you like

@Justice every class is in a different file named as the class, and I would like to avoid to hit the file system to look for the files

You can do it in reverse by using class_parents (php.net/manual/en/function.class-parents.php) but you cannot get all extended classes list and you need to build your own logic; for example create an auto loader and through the auto loader get the parent class and save it somewhere (if does not exists)

1 Answer 1

I would use scandir(C:// . /[directory with files in]); to get an array containing all files and folders in that selected directory.

I would then remove ‘.’ and ‘..’ as these are for navigation of directories. Then in a foreach() loop use if(! is_dir($single_item)) to get all files that aren’t directories. After this you have a list of files and directories. I would then remove the directory navigation ‘.’ and ‘..’ from the array.

Then as before I would read the contents of the file using file_get_contents(), then split the words using explode() exploding by a [space]. I would then use a regex expression ‘~MyClass[A-Za-z0-9]~’ (or other applicable expression) using preg_match() and store all matches in an array. I would finally filter these by using array_filter() to get a unique list you can use however you like

//directory to scan $dir = "C:\ . \[directory you want]"; //scan root directory for files $root = scandir($dir); //delete directory listings from array (directory navigation) $disallowed_values = array(".", ".."); foreach($disallowed_values as $disallowed) < if(($key = array_search($disallowed, $root)) !== false) < unset($root[$key]); >> //if array is not empty (no files / folders found) if(! empty($root)) < //empty array for items you want found. $class_array = array(); //for each directory foreach($root as $item) < if(! is_dir("$dir" . DIRECTORY_SEPARATOR . "$item")) < //get file contents $file_content = file_get_contents("$dir" . DIRECTORY_SEPARATOR . "$item"); //pattern to search for $pattern = "~MyClass[A-Za-z0-9]*~"; //create array with results for single file preg_match_all($pattern, $file_content, $result); //use $result to populate class_array(); use print_r($result); to check what it is outputting (based on your file's structures) >> > //get unique items from array_filter - remove duplicates $class_array = array_filter($class_array); //use array of items however you like 

Источник

Оцените статью