简体   繁体   English

PHP继承的父方法无法访问子属性的私有属性

[英]PHP Inherited parent method can't access child's private property

First of all: A quite similar problem has been posted and somehow solved already, but is still not answering my specific problem. 首先:一个非常相似的问题已经发布并且已经以某种方式解决了,但仍然没有回答我的具体问题。 More about this later. 稍后会详细介绍。

In words: I have a base class which provides some methods to all childs, but doesn't contain any property. 用语言:我有一个基类,它为所有子项提供一些方法,但不包含任何属性。 My child is inheriting these methods, which should be used to access the child's properties. 我的孩子继承了这些方法,这些方法应该用于访问孩子的属性。 If the child's property is protected or public , all works fine, but if the child's property is private , it fails without error (just nothing happens). 如果孩子的财产protectedpublic ,一切正常,但如果孩子的财产是private ,那么它就会失败而没有错误(没有任何反应)。

In code: 在代码中:

class MyBaseClass {
    public function __set($name, $value) {
        if(!property_exists($this, $name))
            throw new Exception("Property '$name' does not exist!");
        $this->$name = $value;
    }
}

class ChildClass extends MyBaseClass {
    public $publicProperty;
    protected $protectedProperty;
    private $privateProperty;
}

$myChild = new ChildClass();
$myChild->publicProperty = 'hello world';    //works of course!
$myChild->protectedProperty = 'hello world'; //works as expected
$myChild->privateProperty = 'hello world';   //doesn't work?

The above mentioned similar problem got the solution to use the magic __set() method to access the private properties, but this I am already doing. 上面提到的类似问题得到了使用magic __set()方法来访问私有属性的解决方案,但我已经这样做了。 If I implement __set() within the child, it works of course, but the idea is, that the child inherits the __set() from it's parent, but obviously it can't access the child's private method. 如果我在子__set()实现__set() ,它当然是有效的,但是这个想法是,子__set()从它的父节点继承了__set() ,但显然它无法访问子节点的私有方法。

Is that on purpose? 这是故意的吗? Am I doinf something wrong? 我做错了吗? or is my approach just crap by design? 或者我的方法只是废话设计?

Background: My original idea was: The whole dynamic thing about __set() is something I don't like. 背景:我最初的想法是:关于__set()的整个动态是我不喜欢的。 Usually a private property should never be accessible from outside, so I implemented throwing __set- and __get-methods in my ultimate base class (from which all classes inherit). 通常永远不能从外部访问私有属性,所以我在我的最终基类中实现了抛出__set-和__get-方法(所有类都从这些方法继承)。

Now I want to dynamicially spawn an instance from an XML file and therefore need access to properties. 现在我想从XML文件动态生成一个实例,因此需要访问属性。 I made the rule, that any XML-instantiatable class needs to implement the magic __set() method and so can be created dynamicially. 我制定了规则,任何XML可实例化的类都需要实现magic __set()方法,因此可以动态创建。 Instead of implementing it in every Class that might be spawned some day, I decided to make them inherit from a class called like class Spawnable { } which provides the needed __set-method. 我决定让它们从类似class Spawnable { }的类中继承,而不是在某天可能生成的每个类中实现它,它提供了所需的__set方法。

This is the difference between private and protected . 这是privateprotected之间的区别。 Private methods and properties cannot be inherited or reached. 无法继承或访问私有方法和属性。 You will need to change them to protected instead. 您需要将它们更改为受保护。

See the manual on visibility 请参阅可见性手册

Members declared protected can be accessed only within the class itself and by inherited and parent classes. 声明受保护的成员只能在类本身以及继承和父类中访问。 Members declared as private may only be accessed by the class that defines the member. 声明为private的成员只能由定义该成员的类访问。

I guess you could fashion something using Reflection. 我想你可以使用Reflection来制作一些东西。 For example, in your Spawnable class: 例如,在您的Spawnable类中:

public function __set($name, $value)
{
    $reflector = new ReflectionClass(get_class($this));
    $prop = $reflector->getProperty($name);
    $prop->setAccessible(true);
    $prop->setValue($this, $value);
}

Not the prettiest of code, though. 不过,这不是最漂亮的代码。

After reviewing my concept, I think it's a bad idea, to go with that approach. 在回顾了我的概念后,我认为采用这种方法是个坏主意。 This is a general issue with PHP's lack of differing between properties and fields. 这是PHP在属性和字段之间缺乏差异的一般问题。 Of course private fields should never be accessible from outside, but only properties, which are defined by the programmer. 当然, 永远不能从外部访问私有字段,而只能访问由程序员定义的属性。 The absence of auto-properties (and I don't mean these magical methods __set() and __get() ) or some conventional rules for property access, makes it difficult to guess, which naming convention has been used by the programmer when implementing setters for private fields in his class. 缺少自动属性(我并不是指这些神奇的方法__set()__get() )或一些传统的属性访问规则,这使得很难猜测程序员在实现setter时使用了哪种命名约定对于他班上的私人领域。

The better concept here might be, to rely on the existence of well-named setters for each spawnable class, although it might break, if someone contributed code, which is not implementing the expected conventional named setters. 这里更好的概念可能是,依赖于每个spawnable类的名称很好的setter的存在,虽然它可能会破坏,如果有人贡献了代码,而没有实现预期的传统命名setter。

However, many thanks for your thoughts and hints! 不过,非常感谢您的想法和提示!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 PHP:为什么子类的继承方法访问父级的私有属性? - PHP: Why do Inherited Methods of Child Class access Parent's Private Properties? 无法访问父类中的子属性(从子对象中的父类继承的调用方法) - Cannot access child property in parent class (calling method inherited from parent in child object) 为什么子代可以覆盖并访问其父私有方法? - Why can child override and access its parent private method? 为什么我可以在父PHP类中访问私有财产? - Why I can access private property in parent php class? PHP - 在链接方法中访问父级的私有变量 - PHP - Access a parent's private variable within a chaining method 无法从 PHP 中的父静态方法访问子静态属性 - Cannot access child static property from parent static method in PHP 父 class 中的私有属性可以通过 PHP 中的子 class 的实例访问和重新分配,但受保护不能 - Private property in parent class can be accessed and re-assigned through the instance of child class in PHP but protected one can't 如果子类继承了受保护的方法,为什么我不能从私有方法访问受保护的方法? - why can't I access a protected method from a private method if the protected ones are inherited by the subclasses? 子类访问父的私有方法? - child class accessing parent's private method? 继承的函数无法访问子类的私有变量 - Inherited function doesn't access private var of the child class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM