为什么这些代码行执行成功


Why do these lines of code execute successfully

我对C++和Java中的OOP非常熟悉,而且我对PHP中的OOP还很陌生,毕竟PHP声称支持OOP。我正在重构实习时给我的一些代码,我发现了以下PHP编码风格。

<?php
    class A {
        public function echoVar(){
            $this->__();
            echo $this->var;
        }
    }
    class B extends A{
        function __(){
            $this->var = 1;
        }
    }
    $v = new B();
    $v->echoVar();

根据我使用C++,尤其是Java的经验,这甚至不会尝试编译,但在PHP中执行很好。我知道所有的语言都不一样,但为什么PHP支持这种风格。这种风格是好的还是坏的做法?这个OOP怎么样?

据我所知,以下是我认为此代码有问题的地方。

  • var不是类B的已定义属性,但已被访问并给定值
  • 超类A如何/为什么可以访问子类B的方法__而不进行强制转换或抽象
  • 我会问A类是如何访问属性var的,但属性本身是用魔法创建的。严肃地说,为什么它可以访问var

我是PHP的OOP新手,所以请帮我澄清这些事情。

这是一个不太好的编码示例。首先,我建议激活严格的错误报告(E_ALL|E_strict|E_NOTICE(。

  1. 如果一个以前没有声明过的类/对象属性被赋值,它将被创建为对象的公共属性。然而,在严格的错误报告中,您会收到一个E_NOTICE。

  2. 虽然__属于B类,但当实例化B时,它可以从A调用。该方法未声明为public/protected/private,因此默认情况下为public,因此父母/子女以及外部都可以访问该方法。

  3. 当然,这通常是一种糟糕的编码风格,至少A会要求在具有以下行的子类中实现__abstract public function __();

  4. 最后,但同样重要的是,函数名__违反了PHP约定,因为以两个下划线开头的方法是保留的。

我将PHP描述为一种在事情不清楚时倾向于做出假设的语言,而C++和Java则是迫使你明确地写出所有内容的语言,否则它们会抛出错误。

问题#1-在PHP中,您不需要明确地声明类属性,以便稍后能够分配它们,正如您所发现的那样。显然,如果您立即尝试在一个类中使用echo $this->var;而不进行赋值,那么它将是未定义的。

问题#2-所以这个有点奇怪,但基本上,如果你从一个子类创建一个超类,并在该子类中定义的方法中调用一个方法,那么就会调用超类版本。因此,即使__()没有在A中定义,它在B中定义,所以如果你创建了一个A对象,并调用echoVar();,你会得到一条关于方法__((未定义的消息,你仍然可以在B类型的对象中调用echoVar();,因为__();是在那里定义的。

问题#3-与#2类似,即使在子类中使用,也将使用变量的超类版本。

然而,我个人会尽量不使用这种风格的编码。我相信你已经意识到了,让一个类依赖于它的超类不是一个好主意。最好明确声明这些事情。

至于OOP,您发布的代码主要使用对象,而不是自由浮动的函数或代码行。