Определение принадлежности объекта к классу
Сейчас мы с вами изучим оператор instanceof . Данный оператор используется для определения того, является ли текущий объект экземпляром указанного класса.
Давайте посмотрим на примере. Пусть у нас даны какие-то два класса:
Создадим объект первого класса:
Проверим принадлежность объекта из переменной $obj первому классу и второму:
Сделайте класс Employee с публичными свойствами name (имя) и salary (зарплата).
Сделайте класс Student с публичными свойствами name (имя) и scholarship (стипендия).
Создайте по 3 объекта каждого класса и в произвольном порядке запишите их в массив $arr .
Переберите циклом массив $arr и выведите на экран столбец имен всех работников.
Аналогичным образом выведите на экран столбец имен всех студентов.
Переберите циклом массив $arr и с его помощью найдите сумму зарплат работников и сумму стипендий студентов. После цикла выведите эти два числа на экран.
Оператор instanceof и наследование
Пусть теперь у нас есть родительский класс и дочерний:
Создадим объект дочернего класса:
Проверим теперь с помощью instanceof , принадлежит ли наш объект классу ParentClass и классу ChildClass :
Как вы видите из примера — оператор instanceof не делает различия при проверки между родительскими и дочерними классами.
Не путайтесь — если объект будет действительно родительского класса то, конечно же, проверка на принадлежность к дочернему классу вернет false :
Сделайте класс User с публичным свойствами name и surname .
Сделайте класс Employee , который будет наследовать от класса User и добавлять свойство salary .
Сделайте класс City с публичными свойствами name и population .
Создайте 3 объекта класса User , 3 объекта класса Employee , 3 объекта класса City , и в произвольном порядке запишите их в массив $arr .
Переберите циклом массив $arr и выведите на экран столбец свойств name тех объектов, которые принадлежат классу User или потомку этого класса.
Переберите циклом массив $arr и выведите на экран столбец свойств name тех объектов, которые не принадлежат классу User или потомку этого класса.
Переберите циклом массив $arr и выведите на экран столбец свойств name тех объектов, которые принадлежат именно классу User , то есть не классу City и не классу Employee .
Применение
Давайте рассмотрим применение оператора instanceof на достаточно сложном примере. Пусть у нас есть вот такой класс для работников:
Пусть также есть такой класс для студентов:
Как вы видите, и работник, и студент имеют имя и какой-то доход: у работника это зарплата, а у студента — стипендия.
Пусть теперь мы хотим сделать класс UsersCollection , предназначенный для хранения работников и студентов. Работников мы будем хранить в свойстве employees , а студентов — в свойстве students :
Давайте теперь реализуем единый метод add для добавления и работников, и студентов. Этот метод параметром будет принимать объект и, если это работник — добавлять его в массив работников, а если студент — в массив студентов. Пример того, как мы будем пользоваться методом нашим методом после его реализации:
add(new Employee(‘john’, 200)); // попадет к работникам $usersCollection->add(new Student(‘eric’, 100)); // попадет к студентам ?>?php>
Итак, давайте реализуем описанный метод add . Здесь нам и поможет изученный нами оператор instanceof :
Давайте также реализуем методы для нахождения суммарной зарплаты и суммарной стипендии:
employees[] = $user; > if ($user instanceof Student) < $this->students[] = $user; > > // Получаем суммарную зарплату: public function getTotalSalary() < $sum = 0; foreach ($this->employees as $employee) < $sum += $employee->getSalary(); > return $sum; > // Получаем суммарную стипендию: public function getTotalScholarship() < $sum = 0; foreach ($this->students as $student) < $sum += $student->getScholarship(); > return $sum; > > ?>?php>
Реализуем также метод, который будет находить общую сумму платежей и работникам, и студентам:
employees[] = $user; > if ($user instanceof Student) < $this->students[] = $user; > > public function getTotalSalary() < $sum = 0; foreach ($this->employees as $employee) < $sum += $employee->getSalary(); > return $sum; > public function getTotalScholarship() < $sum = 0; foreach ($this->students as $student) < $sum += $student->getScholarship(); > return $sum; > // Получаем общую сумму платежей и работникам, и студентам: public function getTotalPayment() < return $this->getTotalScholarship() + $this->getTotalSalary(); > > ?>?php>
Проверим работу нашего класса:
add(new Student(‘kyle’, 100)); $usersCollection->add(new Student(‘luis’, 200)); $usersCollection->add(new Employee(‘john’, 300)); $usersCollection->add(new Employee(‘eric’, 400)); // Получим полную сумму стипендий: echo $usersCollection->getTotalScholarship(); // Получим полную сумму зарплат: echo $usersCollection->getTotalSalary(); // Получим полную сумму платежей: echo $usersCollection->getTotalPayment(); ?>?php>
Скопируйте мой код классов Employee и Student и самостоятельно не подсматривая в мой код реализуйте такой же класс UsersCollection .
class_exists
Эта функция проверяет, был ли объявлен указанный класс или нет.
Список параметров
Имя класса. Воспринимается без учета регистра.
Возвращаемые значения
Возвращает TRUE , если класс class_name объявлен, иначе FALSE .
Список изменений
Версия | Описание |
---|---|
5.0.2 | Больше не возвращает TRUE для объявленных интерфейсов. Используйте для этого interface_exists() . |
Примеры
Пример #1 Пример использования class_exists()
// Проверяем существование класса перед его использованием
if ( class_exists ( ‘MyClass’ )) $myclass = new MyClass ();
>
?php
Пример #2 Пример использования параметра autoload
function __autoload ( $class )
include( $class . ‘.php’ );
?php
// Проверяем необходимость подключения указанного класса
if (! class_exists ( $class , false )) trigger_error ( «Unable to load class: $class » , E_USER_WARNING );
>
>
if ( class_exists ( ‘MyClass’ )) $myclass = new MyClass ();
>
Смотрите также
- function_exists() — Возвращает TRUE, если указанная функция определена
- interface_exists() — Проверяет, определен ли интерфейс
- get_declared_classes() — Возвращает массив с именами объявленных классов
class_exists
Эта функция проверяет, был ли объявлен указанный класс или нет.
Список параметров
Имя класса. Воспринимается без учёта регистра.
Нужно ли автоматически подгружать класс, если он ещё не загружен.
Возвращаемые значения
Возвращает true , если класс class объявлен, иначе false .
Примеры
Пример #1 Пример использования class_exists()
// Проверяем существование класса перед его использованием
if ( class_exists ( ‘MyClass’ )) $myclass = new MyClass ();
>
?php
Пример #2 Пример использования c параметром autoload
spl_autoload_register (function ( $class_name ) include $class_name . ‘.php’ ;
?php
// Проверяем необходимость подключения указанного класса
if (! class_exists ( $class_name , false )) throw new LogicException ( «Unable to load class: $class_name » );
>
>);
if ( class_exists ( MyClass ::class)) $myclass = new MyClass ();
>
Смотрите также
- function_exists() — Возвращает true, если указанная функция определена
- enum_exists() — Проверяет, определено ли перечисление
- interface_exists() — Проверяет, определён ли интерфейс
- get_declared_classes() — Возвращает массив с именами объявленных классов
User Contributed Notes 9 notes
If you are using aliasing to import namespaced classes, take care that class_exists will not work using the short, aliased class name — apparently whenever a class name is used as string, only the full-namespace version can be used
use a\namespaced\classname as coolclass;
class_exists( ‘coolclass’ ) => false
Note: class_exists() check only classes!
interface DemoInterface <>;
var_dump ( class_exists ( ‘DemoInterface’ )); // false
trait DemoTrait <>;
var_dump ( class_exists ( ‘DemoTrait’ )); // false
class DemoClass <>;
var_dump ( class_exists ( ‘DemoClass’ )); // true
?>
Common function:
/**
* Checks if the class/trait/interface has been defined.
*
* @param string $name The case-insensitive name of class/trait/interface
* @param bool $autoload Whether to call spl_autoload()
* @return bool
*/
function structure_exists ( string $name , bool $autoload = true ): bool
return class_exists ( $name , $autoload )
|| interface_exists ( $name , $autoload )
|| trait_exists ( $name , $autoload );
>
?>
Beware: class_exists is case-INsensitive, as is class instantiation.
php > var_dump(class_exists(«DomNode»));
bool(true)
php > var_dump(class_exists(«DOMNode»));
bool(true)
php > var_dump(class_exists(«DOMNodE»));
bool(true)
php > $x = new DOMNOdE();
php > var_dump(get_class($x));
string(7) «DOMNode»
(tested with PHP 5.5.10 on Linux)
This can cause some headaches in correlating class names to file names, especially on a case-sensitive file system.
If you recursively load several classes inside an autoload function (or mix manual loading and autoloading), be aware that class_exists() (as well as get_declared_classes()) does not know about classes previously loaded during the *current* autoload invocation.
Apparently, the internal list of declared classes is only updated after the autoload function is completed.
Hi guys!
Be careful and don’t forget about second boolean argument $autoload (TRUE by default) when check exists class after spl_autoload_register. Propose short example
file second.php
class Second <>
?>
file index.php
class First
function first ( $class , $bool ) spl_autoload_register ( function( $class ) require strtolower ( $class ) . ‘.php’ ;
>);
echo class_exists ( $class , $bool )? ‘Exist. ‘ : ‘Not exist!’ ;
>
>
new First ( $class = ‘Second’ , $bool = true ); //Exist.
new First ( $class = ‘Second’ , $bool = false ); //Not exist!
?>
Because __autoload executing much earlier than boolean returned, imho..
If you are checking if a class exists that is in a specific namespace then you have to pass in the full path to the class:
echo (class_exists(«com::richardsumilang::common::MyClass»)) ? «Yes» : «No»;
If you have a directory of classes you want to create. (Modules in my instance). you can do it like that
I’m running PHP 5.3.4 on Windows 7 and had some difficulty autoloading classes using class_exists(). In my case, when I checked for the class and it didn’t exist, class_exists automatically threw a system Exception. I was also throwing my own exception resulting in an uncaught exception.
/**
* Set my include path here
*/
$include_path = array( ‘/include/this/dir’ , ‘/include/this/one/too’ );
set_include_path ( $include_path );
spl_autoload_register ();
/**
* Assuming I have my own custom exception handler (MyException) let’s
* try to see if a file exists.
*/
try if( ! file_exists ( ‘myfile.php’ ) ) throw new MyException ( ‘Doh!’ );
>
include( ‘myfile.php’ );
>
catch( MyException $e ) echo $e -> getMessage ();
>
/**
* The above code either includes myfile.php or throws the new MyException
* as expected. No problem right? The same should be true of class_exists(),
* right? So then.
*/
$classname = ‘NonExistentClass’ ;
try if( ! class_exists ( $classname ) ) throw new MyException ( ‘Double Doh!’ );
>
$var = new $classname ();
>
catch( MyException $e ) echo $e -> getMessage ();
>
/**
* Should throw a new instance of MyException. But instead I get an
* uncaught LogicException blah blah blah for the default Exception
* class AND MyException. I only catch MyException so we’ve got on
* uncaught resulting in the dreaded LogicException error.
*/
?>
By registering an additional autoload handler function that did nothing, I was able to stop throwing the extra Exception and only throw my own.
/**
* Set my include path here
*/
$include_path = array( ‘/include/this/dir’ , ‘/include/this/one/too’ );
set_include_path ( $include_path );
spl_autoload_register ();
spl_autoload_register ( ‘myAutoLoad’ ); // Add these two and no worries.
function myAutoLoad () <>
/**
* By registering the additional custom autoload function that does nothing
* class_exists() returns only boolean and does NOT throw an uncaught Exception
*/
?>
Found this buried in some search results. I don’t remember the page URL but if it would have been here it might have saved me some time!
If spl_autoload_register() had been called, then function will try autoload class if it does not exists.
Use instead
in_array ( $class_name , get_declared_classes ());
?>
- Функции работы с классами и объектами
- class_alias
- class_exists
- enum_exists
- get_called_class
- get_class_methods
- get_class_vars
- get_class
- get_declared_classes
- get_declared_interfaces
- get_declared_traits
- get_mangled_object_vars
- get_object_vars
- get_parent_class
- interface_exists
- is_a
- is_subclass_of
- method_exists
- property_exists
- trait_exists
- __autoload