Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 从公共基函数访问类层次结构中的私有属性_Php_Polymorphism - Fatal编程技术网

Php 从公共基函数访问类层次结构中的私有属性

Php 从公共基函数访问类层次结构中的私有属性,php,polymorphism,Php,Polymorphism,我想在基类中定义一个方法,并在类层次结构中的连续构造函数中调用它。每次调用它时,我希望它对调用它的类的属性进行操作 例如,A是基类,方法在这里定义。B从A继承,C从B继承 当我实例化具体的类C时,构造函数将调用基类方法,我希望它对C的属性进行操作(这将是一个私有数组,我将在初始化它时填充它) 然后C的构造函数调用父::\u construct。当B构造函数调用基类方法时,该方法应该对B的属性进行操作。在B构造函数完成之前,它将调用父::u construct,而A构造函数将对A的属性进行操作 我

我想在基类中定义一个方法,并在类层次结构中的连续构造函数中调用它。每次调用它时,我希望它对调用它的类的属性进行操作

例如,A是基类,方法在这里定义。B从A继承,C从B继承

当我实例化具体的类C时,构造函数将调用基类方法,我希望它对C的属性进行操作(这将是一个私有数组,我将在初始化它时填充它)

然后C的构造函数调用
父::\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
也不起作用,因为这样子对象将重写父属性

解决这个问题的办法不是让have
C
成为a(is-a),而是让have
C
具有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,很好的一个。事后看来,你让事情变得显而易见!