Here is some clarification about PHP inheritance – there is a lot of bad information on the net. PHP does support Multi-level inheritance. (I tested it using version 5.2.9). It does not support multiple inheritance.
This means that you cannot have one class extend 2 other classes (see the extends keyword). However, you can have one class extend another, which extends another, and so on.
Example:
<?php
class A {
// more code here
}
class B extends A {
// more code here
}
class C extends B {
// more code here
}
$someObj = new A(); // no problems
$someOtherObj = new B(); // no problems
$lastObj = new C(); // still no problems
?>Наследување на објекти
Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.
Наследување на објекти
Референца за `language.oop5.inheritance.php` со подобрена типографија и навигација.
Наследување на објекти
Наследувањето е добро воспоставен програмски принцип, а PHP го користи овој принцип во својот објектен модел. Овој принцип ќе влијае на начинот на кој многу класи и објекти се поврзани едни со други.
На пример, при проширување на класа, подкласата наследува сите јавни и заштитени методи, својства и константи од родителската класа. Освен ако класата не ги надмине тие методи, тие ќе ја задржат својата оригинална функционалност.
Ова е корисно за дефинирање и апстрахирање на функционалност, и дозволува имплементација на дополнителна функционалност во слични објекти без потреба од повторно имплементирање на целата споделена функционалност.
Приватните методи на родителската класа не се достапни за подкласата. Како резултат на тоа, подкласите можат самите да го имплементираат приватниот метод без да ги земаат предвид нормалните правила за наследување. Сепак, пред PHP 8.0.0, final and static
беа применети ограничувања на приватните методи. Од PHP 8.0.0, единственото ограничување за приватни методи што се применува е private final конструкторите, бидејќи тоа е вообичаен начин за „оневозможување“ на конструкторот кога се користат статички методи за фабрикување наместо тоа.
На visibility
методи, својства и константи може да се релаксираат, на пр. а
protected метод може да се означи како
public, но тие не можат да се ограничат, на пр. означување на public својство како private. Исклучок се конструкторите, чија видливост може да се ограничи, на пр. а public конструктор може да се означи како private
во подкласа.
Забелешка:
Освен ако не се користи авто-вчитање, класите мора да бидат дефинирани пред да се користат. Ако една класа проширува друга, тогаш родителската класа мора да биде декларирана пред структурата на подкласата. Ова правило важи за класи кои наследуваат други класи и интерфејси.
Забелешка:
Не е дозволено да се надмине својство за читање-запишување со само за читање својство или обратно.
<?php
class A {
public int $prop;
}
class B extends A {
// Illegal: read-write -> readonly
public readonly int $prop;
}
?>
Пример #1 Пример за наследување
<?php
class Foo
{
public function printItem($string)
{
echo 'Foo: ' . $string . PHP_EOL;
}
public function printPHP()
{
echo 'PHP is great.' . PHP_EOL;
}
}
class Bar extends Foo
{
public function printItem($string)
{
echo 'Bar: ' . $string . PHP_EOL;
}
}
$foo = new Foo();
$bar = new Bar();
$foo->printItem('baz'); // Output: 'Foo: baz'
$foo->printPHP(); // Output: 'PHP is great'
$bar->printItem('baz'); // Output: 'Bar: baz'
$bar->printPHP(); // Output: 'PHP is great'
?>Компатибилност на типот на враќање со внатрешни класи
Пред PHP 8.1, повеќето внатрешни класи или методи не ги декларираа своите типови на враќање, и беше дозволен каков било тип на враќање при нивно проширување.
Од PHP 8.1.0, повеќето внатрешни методи почнаа „привремено“ да го декларираат својот тип на враќање, во тој случај типот на враќање на методите треба да биде компатибилен со родителот што се проширува; инаку, се емитува известување за застарување. Имајте предвид дека недостатокот на експлицитна декларација за враќање исто така се смета за неусогласеност на потписот, и затоа резултира со известување за застарување.
If the return type cannot be declared for an overriding method due to PHP cross-version compatibility concerns, a ReturnTypeWillChange Ако типот на враќање не може да се декларира за надредена метода поради проблеми со компатибилноста на PHP верзиите, може да се додаде
атрибут за да се пригуши известувањето за застареност.
<?php
class MyDateTime extends DateTime
{
public function modify(string $modifier) { return false; }
}
// "Deprecated: Return type of MyDateTime::modify(string $modifier) should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice" as of PHP 8.1.0
?>Пример #2 Надредената метода не декларира тип на враќање
<?php
class MyDateTime extends DateTime
{
public function modify(string $modifier): ?DateTime { return null; }
}
// "Deprecated: Return type of MyDateTime::modify(string $modifier): ?DateTime should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice" as of PHP 8.1.0
?>Пример #3 Надредената метода декларира погрешен тип на враќање
<?php
class MyDateTime extends DateTime
{
/**
* @return DateTime|false
*/
#[\ReturnTypeWillChange]
public function modify(string $modifier) { return false; }
}
// No notice is triggered
?>Белешки од корисници Управување со PDO конекции
I think the best way for beginners to understand inheritance is through a real example so here is a simple example I can gave to you
<?php
class Person
{
public $name;
protected $age;
private $phone;
public function talk(){
//Do stuff here
}
protected function walk(){
//Do stuff here
}
private function swim(){
//Do stuff here
}
}
class Tom extends Person
{
/*Since Tom class extends Person class this means
that class Tom is a child class and class person is
the parent class and child class will inherit all public
and protected members(properties and methods) from
the parent class*/
/*So class Tom will have these properties and methods*/
//public $name;
//protected $age;
//public function talk(){}
//protected function walk(){}
//but it will not inherit the private members
//this is all what Object inheritance means
}In case you have a public readonly property in a class you need to extend, adding other properties, this can be a way to do it:
<?php
class A {
public function __construct(
public readonly int $prop
) {}
}
class B extends A {
public function __construct(
int $prop,
public readonly int $prop2
) {
parent::__construct($prop);
}
}
?>The Idea that multiple inheritence is not supported is correct but with tratits this can be reviewed.
for e.g.
<?php
trait custom
{
public function hello()
{
echo "hello";
}
}
trait custom2
{
public function hello()
{
echo "hello2";
}
}
class inheritsCustom
{
use custom, custom2
{
custom2::hello insteadof custom;
}
}
$obj = new inheritsCustom();
$obj->hello();
?>You can force a class to be strictly an inheritable class by using the "abstract" keyword. When you define a class with abstract, any attempt to instantiate a separate instance of it will result in a fatal error. This is useful for situations like a base class where it would be inherited by multiple child classes yet you want to restrict the ability to instantiate it by itself.
Example........
<?php
abstract class Cheese
{
//can ONLY be inherited by another class
}
class Cheddar extends Cheese
{
}
$dinner = new Cheese; //fatal error
$lunch = new Cheddar; //works!
?>I was recently extending a PEAR class when I encountered a situation where I wanted to call a constructor two levels up the class hierarchy, ignoring the immediate parent. In such a case, you need to explicitly reference the class name using the :: operator.
Fortunately, just like using the 'parent' keyword PHP correctly recognizes that you are calling the function from a protected context inside the object's class hierarchy.
E.g:
<?php
class foo
{
public function something()
{
echo __CLASS__; // foo
var_dump($this);
}
}
class foo_bar extends foo
{
public function something()
{
echo __CLASS__; // foo_bar
var_dump($this);
}
}
class foo_bar_baz extends foo_bar
{
public function something()
{
echo __CLASS__; // foo_bar_baz
var_dump($this);
}
public function call()
{
echo self::something(); // self
echo parent::something(); // parent
echo foo::something(); // grandparent
}
}
error_reporting(-1);
$obj = new foo_bar_baz();
$obj->call();
// Output similar to:
// foo_bar_baz
// object(foo_bar_baz)[1]
// foo_bar
// object(foo_bar_baz)[1]
// foo
// object(foo_bar_baz)[1]
?>Documentation says: Private methods of a parent class are not accessible to a child class. As a result, "child classes may reimplement a private method themselves without regard for normal inheritance rules."
So it is not very obvious what this will output:
<?php
class Bar {
private function one() {
echo "Bar::one()\n";
}
public function run() {
echo "Bar::run()\n";
$this->one();
}
}
class Foo extends Bar {
private function one() {
echo "Foo::one()\n";
}
}
(new Foo())->run();
?>
Bar::run()
Bar::one()
A common sense next step would be to try make the method "one" in Foo public,
but this does not work either if the caller is the parent class.
For the parent to be able to direct the child class
both need to be public or you must call the method explicitly on the child class:
<?php
(new Foo())->one();
?>