Php 从公共基函数访问类层次结构中的私有属性
我想在基类中定义一个方法,并在类层次结构中的连续构造函数中调用它。每次调用它时,我希望它对调用它的类的属性进行操作 例如,A是基类,方法在这里定义。B从A继承,C从B继承 当我实例化具体的类C时,构造函数将调用基类方法,我希望它对C的属性进行操作(这将是一个私有数组,我将在初始化它时填充它) 然后C的构造函数调用Php 从公共基函数访问类层次结构中的私有属性,php,polymorphism,Php,Polymorphism,我想在基类中定义一个方法,并在类层次结构中的连续构造函数中调用它。每次调用它时,我希望它对调用它的类的属性进行操作 例如,A是基类,方法在这里定义。B从A继承,C从B继承 当我实例化具体的类C时,构造函数将调用基类方法,我希望它对C的属性进行操作(这将是一个私有数组,我将在初始化它时填充它) 然后C的构造函数调用父::\u construct。当B构造函数调用基类方法时,该方法应该对B的属性进行操作。在B构造函数完成之前,它将调用父::u construct,而A构造函数将对A的属性进行操作 我
父::\u construct
。当B构造函数调用基类方法时,该方法应该对B的属性进行操作。在B构造函数完成之前,它将调用父::u construct
,而A构造函数将对A的属性进行操作
我正在查看LSB,但它无法正常工作,因为父::\u构造是一个转发呼叫。我尝试使用get\u parent\u class()
的结果来代替parent::
,但对static::propertyName
的调用出错,因为propertyName
不是常量
我该怎么做
编辑:下面是一个代码示例。下面的代码输出“pq pq”。我希望它输出“pqrstu”
如果我没弄错的话,这就是你的例子:
class A {
public function __construct() {
}
public function someMethod($arg) {
$someProperty = $arg;
}
}
class B extends A {
public function __construct() {
parent::__construct();
}
}
class C extends B {
private $someProperty;
public function __construct() {
parent::__construct();
}
}
一切都如你所料。只有一个问题,;A类没有属性someProperty
。如果你想在A类中使用它,你必须在那里定义它。如果你想在子类中使用它,你必须使它受到保护。因此,您的A级必须如下所示:
class A {
protected $someProperty;
public function __construct() {
}
public function someMethod($arg) {
$this->someProperty = $arg;
}
}
class A {
private $property = array('P','Q');
function __construct() {
$this->myMethod();
}
public function myMethod() {
foreach ($this->property as $value) {
echo $value . " ";
}
}
}
class B extends A {
private $property = array('R','S');
function __construct()
{
parent::__construct();
$this->myMethod();
}
public function myMethod() {
foreach ($this->property as $value) {
echo $value . " ";
}
}
}
class C extends B {
private $property = array('T','U');
function __construct()
{
parent::__construct();
$this->myMethod();
}
public function myMethod() {
foreach ($this->property as $value) {
echo $value . " ";
}
}
}
$c = new C();
现在,您可以在类B和C中使用它,类A可以将属性与someMethod
一起使用:
$instance = new C();
$instance->someMethod("test");
据我所知,这是不可能的。在私有的情况下,变量对方法不可用,在公共/受保护的情况下,变量被覆盖
通过考试你可以得到你想要的结果
$this->property
在每个myMethod调用中,如下所示-
$this->myMethod($this->property)
因为您的示例将$property
定义为private
,并且您从不重写myMethod
,当实例化C
或B
类型的对象时,它会运行类A
的构造函数,该构造函数调用myMethod()
来自类A
,其中$property
的值是数组('P','Q')代码>
如果您希望它打印'pqrstu',您必须重写myMethod()
,并从每个单独的类调用它,\uu construct()
方法,或者声明$property
受保护,以便子类可以覆盖其值
大概是这样的:
class A {
protected $someProperty;
public function __construct() {
}
public function someMethod($arg) {
$this->someProperty = $arg;
}
}
class A {
private $property = array('P','Q');
function __construct() {
$this->myMethod();
}
public function myMethod() {
foreach ($this->property as $value) {
echo $value . " ";
}
}
}
class B extends A {
private $property = array('R','S');
function __construct()
{
parent::__construct();
$this->myMethod();
}
public function myMethod() {
foreach ($this->property as $value) {
echo $value . " ";
}
}
}
class C extends B {
private $property = array('T','U');
function __construct()
{
parent::__construct();
$this->myMethod();
}
public function myMethod() {
foreach ($this->property as $value) {
echo $value . " ";
}
}
}
$c = new C();
或者这个:
class A {
protected $property = array('P','Q');
function __construct() {
$this->myMethod();
}
public function myMethod() {
foreach ($this->property as $value) {
echo $value . " ";
}
}
}
class B extends A {
protected $property = array('R','S');
function __construct()
{
parent::__construct();
$this->myMethod();
}
}
class C extends B {
protected $property = array('T','U');
function __construct()
{
parent::__construct();
$this->myMethod();
}
}
$c = new C();
property
不能在子类中重载。一旦您拥有了C
,它就不再具有a
的私有属性。它无法访问它们(在反射之外)。您能够做到这一点的唯一方法是在链中将属性传递给someMethod
,但这需要访问所需的属性
使用protected
也不起作用,因为这样子对象将重写父属性
解决这个问题的办法不是让haveC
成为a(is-a),而是让haveC
具有a
的属性(has-a..composition)。不过,这需要对层次结构进行一些修改,并且您的调用必须更加明确。差不多
class C {
private $b;
private $properties = array('T', 'U');
public function __construct(B $b) {
$this->b = $b;
}
public function someMethod() {
$this->b->someMethod($properties);
}
}
class B {
private $properties = array('R', 'S');
private $a;
public function __construct(A $a) {
$this->a = $a;
}
public function someMethod($properties) {
$this->a->someMethod(array_merge($this->properties, $properties));
}
}
class A {
private $properties = array('P', 'Q');
public function someMethod($properties) {
//your implementation plus an array_merge
}
}
这显然增加了定义中的冗长,这是不好的。你可能想重新考虑为什么你必须用你现在的方式做一些事情。您可以使用trait
s(假设您使用的是PHP5.4)谢谢Matt。根据你的第一个例子,我不想重复这种方法。至于第二个例子,我尝试了这个,但是C::property覆盖了A和B,所以我最终得到了TUTU。嘿,kewlashu,很好的一个。事后看来,你让事情变得显而易见!