oop — конструктор может получить доступ к родительским частным свойствам в PHP?

При работе с наследованием в PHP я обнаружил недостаток знаний, в основном о конструкторы а также частный свойства.

Давайте возьмем этот код в качестве примера:

<?php

class Module
{
public $type;
public function __construct($type)
{
$this->type = $type;
}
}

class BModule extends Module
{
}

class CModule extends BModule
{
}

class A
{
private $module;
public function __construct(Module $module)
{
echo 'Set module for '.__CLASS__.' to '.$module->type . PHP_EOL;
echo "<br>";
$this->module = $module;
}

public function getModule()
{
echo "I (as " . __CLASS__ . ") have a module of type " . $this->module->type;
return $this->module->type;
}
}

class B extends A
{
}$m = new Module('base-module');
$bm = new BModule('bi-module');

echo "<br>--------A---------<br>";
$a = new A($m);
echo "<br>A is of type " . $a->getModule();
echo "<br>--------B---------<br>";
$b = new B($bm);
echo "<br>B is of type " . $b->getModule();

Некоторые вопросы:

  1. не должна ли конструкция B вызывать конструктор в контексте B? (и поэтому я ожидаю, что он потерпит неудачу, потому что он не унаследовал частную собственность $ модуль)
    • или PHP просто вызовет конструктор A, используя / ссылаясь на методы и свойства из A? (в том числе частный из них)
  2. Я могу перейти к $ б либо модуль или BModule объект; это потому что BModule это ребенок модуль. Проверяет ли PHP некоторую цепочку наследования (проверяет родителей) переданного объекта при проверке подсказки типа?
    • так что я могу передать конструктору либо объект типа модуль или же BModule или же CModule?

И это еще один пример:

<?phpclass a
{
private $a;
protected $a_copy;

public function __construct($a_value)
{
$this->a = $a_value;
$this->a_copy = $this->a;
}

public function getA()
{
return $this->a;
}
public function getCopyA()
{
return $this->a;
}
}

class b extends a
{
}$a = new a('value for a');
$b = new b('value for b');
echo "<br>-----A-----<br>";
echo $a->getA()."<br>";
echo $a->getCopyA()."<br>";
echo "<br>-----B-----<br>";
echo $b->getA()." (I would expect to have no access to \$a)<br>";
echo $b->getCopyA()."<br>";

Быть собственностью $ а приват, я ожидать, что не сможет получить к нему доступ или сделать что-нибудь с ним из класса б.
Это немного бессмысленно для моего настоящего понимания.

0

Решение

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

Итак, чтобы коротко ответить на ваши вопросы:

  1. Нет, функции всегда вызываются в контексте того, где они находятся определенный, не откуда они называются.
  2. PHP проверит всю цепочку наследования, чтобы убедиться, что она правильная. Можно предположить, что любой дочерний элемент класса имеет те же функции. Поэтому, если B расширяет A, вы можете использовать либо B, либо A в качестве параметра, когда он намекает на тип A, но использовать B, только если он намекает на тип B
1

Другие решения

Объявление 1: Нет, контекст вызываемого метода — это место, где метод (в данном случае конструктор) объявлен. Если контекст будет классом B тогда любой может сломать ваш класс, просто расширив его.

Взгляните на этот пример:

class A
{
private $module;
public function __construct(Module $module)
{
echo 'Set module for '.__CLASS__.' to '.$module->type . PHP_EOL;
echo "<br>";
$this->module = $module;
}
}

class B extends A
{
public function __construct()
{
parent::__construct(new Module()); // call the parent (which is A)
}
}

Это показывает, как сфера A::__construct() на самом деле A учебный класс.

Объявление 2: Да, каждый объект, который является экземпляром подкласса, может использоваться вместо суперкласса. Вот почему вы должны писать свои классы, чтобы они могли быть заменены, когда статическая типизация требует суперкласса. Для получения дополнительной информации по этому вопросу см. Принцип подстановки Лискова.

Что касается последнего примера: снова нет кода в подклассе, который работал бы с частными членами суперкласса. Весь код работает в контексте суперкласса. Так что здесь нет проблем.

Если вы попытаетесь перегрузить методы суперкласса и использовать его закрытые члены, вот что:

class b extends a
{
public function getA()
{
return $this->a . "_suffix"; // error
}
}

В таком случае вы должны зависеть от реализации getA() метод в суперклассе:

class b extends a
{
public function getA()
{
return parent::getA() . "_suffix"; // ok, we are depending on the super class implementation
}
}
1

По вопросам рекламы [email protected]