PHP属性访问和美元符号

11

最近我在加强我对PHP的学习。作为一名来自JavaScript的开发者,我发现PHP的对象模型要简单一些。

但我也遇到了一些奇怪的问题,想要有些澄清,但文档中好像找不到相关信息。

在PHP中定义类时,你可以像这样定义属性:

class myClass {

    public $myProp = "myProp";
    static $anotherProp = "anotherProp";

}
拥有公共变量$myProp,我们可以使用(假设myClass被引用在一个名为$myClass的变量中)$myClass->myProp来访问它,而不需要使用美元符号。
只能使用::来访问静态变量。所以,我们可以像这样使用美元符号访问静态变量:$myClass::$anotherProp
问题是,为什么我们必须在::上使用美元符号而不是->??
编辑:
以下是我认为会起作用(并且确实起作用)的代码:
class SethensClass {

    static public $SethensProp = "This is my prop!";

}

$myClass = new SethensClass;
echo $myClass::$SethensProp;

1
有趣...一个赞同和一个关闭请求。 - Sethen
很抱歉在这里评论你的另一个问题(如果按照一系列单独的问题提问,我个人认为是可以的-例如,请参阅 http://stackoverflow.com/questions/15270843/what-does-plus-operator-mean-in-underscore-js),但是像“最佳实践建议这样做”这样的说法有点无意义。如果你不能解释*为什么*你认为某件事是“最佳实践”,那么你怎么知道它是“最佳”的呢?不同的情况下有不同的最佳方案。 - Paul D. Waite
@PaulD.Waite 没关系。作为一名试图推进开发的开发人员,询问特定库是否遵循最佳实践以帮助他们学习是可以接受的。但是,如果整个社区不支持这一点,那么非常令人沮丧。我不相信特定的库是使用最佳实践编写的,我正在努力确保这不是我的问题,以便在贡献代码时,我可以确信它是最好的。 - Sethen
很酷。只要记住,为了让你的代码变得更好,你需要超越“有人说这是最佳实践”的层面,理解为什么某些东西被认为是好的或最佳实践。 - Paul D. Waite
2个回答

18

类常量使用::作用域运算符访问,而不需要美元符号($),因此在这里需要$来区分静态类属性和类常量。

class myClass {
  public static $staticProp = "static property";

  const CLASS_CONSTANT = 'a constant';
}

echo myClass::CLASS_CONSTANT;
echo myClass::$staticProp;

因此,访问变量时必须使用$。但是在类名的开头放置$,比如$myClass::staticProp是不允许的,因为解析器无法识别类名,因为还可以将变量用作类名。因此,它必须附加到属性上。

$myClass = "SomeClassName";
// This attempts to access a constant called staticProp
// in a class called "SomeClassName"
echo $myClass::staticProp;

// Really, we need
echo myClass::$staticProp;

$myClass 应该代表 $myClass = new myClass - Sethen
@LimH。这只是一种不好的做法吗?因为我曾经成功地通过类实例访问了“static”变量。 - Sethen
@SethenMaleno 静态属性应该静态使用,如果您尝试通过 $this->staticProp 访问它们,则违反了严格标准。 - Michael Berkowski
1
@SethenMaleno 对不起,对我的无知感到非常非常非常抱歉。根据文档,在PHP 5.3.0中,您可以从变量引用类。因此,从技术上讲,您不能在实例上调用类变量,但是由于PHP是PHP,它会自动为您引用类。因此,在您的情况下,$myClass将被解释为SethensClass,而不是实际的类实例,因此可以调用静态变量。 - Lim H.
1
@SethenMaleno 你上面所写的代码是可以工作的。这是一种我通常避免使用的行为,除非绝对必要,但它是合法的,有时也有用。 - Michael Berkowski
显示剩余7条评论

0

它很贪心!

有时候,引用基类中的函数和变量或者引用还没有任何实例的类中的函数是非常有用的。这时可以使用 :: 运算符。

<?php
class A
{
    function example()
    {
        echo "I am the original function A::example().<br>\n";
    }
}

class B extends A
{
    function example()
    {
        echo "I am the redefined function B::example().<br>\n";
        A::example();
    }
}

// there is no object of class A.
// this will print
//   I am the original function A::example().<br>
A::example();

// create an object of class B.
$b = new B;

// this will print 
//   I am the redefined function B::example().<br>
//   I am the original function A::example().<br>
$b->example();
?> 

上面的例子调用了类A中的函数example(),但是没有类A的对象,因此我们不能写$a->example()或类似的代码。相反,我们将example()作为“类函数”调用,也就是说,作为该类本身的函数,而不是该类的任何对象的函数。

有类函数,但没有类变量。实际上,在调用时根本没有对象。因此,类函数可能不使用任何对象变量(但可以使用局部和全局变量),并且它可能根本不使用$this。

在上面的例子中,类B重新定义了函数example()。类A中的原始定义被遮蔽并且不再可用,除非您使用::运算符特别指定在类A中实现example()的方式。使用A::example()来执行此操作(实际上,您应该编写parent::example())。

在这种情况下,存在当前对象,并且它可能具有对象变量。因此,在对象函数内部使用时,可以使用$this和对象变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接