如何从父类函数中访问子类定义的常量?

52

我在php.net上看到了这个例子:

<?php
class MyClass {

     const MY_CONST = "yonder";

     public function __construct() {

          $c = get_class( $this );
          echo $c::MY_CONST;
     }
}

class ChildClass extends MyClass {

     const MY_CONST = "bar";
}

$x = new ChildClass(); // prints 'bar'
$y = new MyClass(); // prints 'yonder'
?>

但是 $c::MY_CONST 只有在5.3.0版本或更高版本中才会被识别。我写的这个类可能会被广泛分发。

基本上,我已经在 ChildClass 中定义了一个常量,并且 MyClass(父类)中的一个函数需要使用该常量。有什么想法吗?

5个回答

122

使用 static::MY_CONST 如何?


3
我不明白为什么其他答案的人要深入探讨面向对象编程。你的解决方案是唯一正确的,而且更加简单易懂。 - Vladimir Hraban
2
使用 static 关键字访问 const 会出现问题,你能解释一下为什么吗?PHP 文档也让我感到困惑。谢谢。 - pavlindrom
4
@checksum:不,那是错误的—— self::MY_CONST 在两种情况下都打印 "yonder"——它是在子类中定义的常量。问题是“如何从父类函数访问在子类中定义的常量”。 - pevik
1
我非常高兴这个能够工作,但是我还是有点疑惑...为什么会这样呢?嗯,不管怎样,我的东西现在可以用了。感谢发帖者! - Dylan Pierce
4
关于实现方法的说明:self::MY_CONST 基于 PHP 5.3.0 中引入的**后期静态绑定**(由 Dmitry、Etienne Kneuss 实现,已在 git 提交中添加了对后期静态绑定的支持)。核心实现在 get_called_class() 函数中。在 PHP <= 5.2.x 的版本中,会出现错误提示:Parse error: syntax error, unexpected T_STATIC - pevik
显示剩余2条评论

28

自 PHP 5.3 起:

使用 static::MY_CONST


更多关于 static 的细节

在这种情况下,关键字 static 是对实际调用类的引用。

这说明了 static $var static::$var self::$var 之间的区别:

class Base {
    const VALUE = 'base';

    static function testSelf() {
        // Output is always 'base', because `self::` is always class Base
        return self::VALUE;
    }

    static function testStatic() {
        // Output is variable: `static::` is a reference to the called class.
        return static::VALUE;
    }
}

class Child extends Base {
    const VALUE = 'child';
}

echo Base::testStatic();  // output: base
echo Base::testSelf();    // output: base

echo Child::testStatic(); // output: child
echo Child::testSelf();   // output: base

还要注意,关键字 static 有两个非常不同的含义:

class StaticDemo {
    static function demo() {
        // Type 1: `static` defines a static variable.
        static $Var = 'bar';

        // Type 2: `static::` is a reference to the called class.
        return static::VALUE;
    }
}

1
很好的解释 - doz87
当使用静态调用静态方法与实例化和调用对象方法时,它的行为是否相同?在每个方法前面加上"static"关键字是令人担忧的。 - NaturalBornCamper
@NaturalBornCamper,Child::testStatic()$child::testStatic()之间没有区别。虽然$child->testStatic()也可以工作,但是对于静态方法,您应该坚持使用:: - 使用->会抛出一个通知,并且可能会让其他开发人员感到困惑。 - Philipp

5

代替

$c = get_class( $this );
echo $c::MY_CONST;

请执行以下操作

$c = get_class( $this );
echo constant($c . '::MY_CONST');

0

我无法使用const使其打印“yonderyonder”(这就是常量的问题,它们不会改变),但使用var可以正常工作:

<?php
class MyClass {

     var $MY_CONST = "yonder";

     public function __construct() {

     echo $this->MY_CONST;
     }
}

class ChildClass extends MyClass {

     var $MY_CONST = "bar";
}

$x = new ChildClass(); // prints 'bar'
$y = new MyClass(); // prints 'yonder'

?>

2
2015年 - 我们不需要var - Herr Nentu'
3
没错,这篇回复是在5年前写的,那时候它还很流行! - Cetra

0
如果你需要访问常量、属性、类或对象的方法,你可以使用反射,它提供了关于对象结构的更多细节。
示例:
class MainClass
{
    const name = 'Primary';

    public $foo = 'Foo Variable';
}
class ExtendedClass extends MainClass
{
    const name = 'Extended';
}

/**
 * From Class Name
 */

//get reflection of main class
$mainReflection = new ReflectionClass('MainClass');

if($mainReflection->hasConstant('name'))
    var_dump($mainReflection->getConstant('name'));//Primary

//get reflection of extended class
$extendedReflection = new ReflectionClass('ExtendedClass');

if($extendedReflection->hasConstant('name'))
    var_dump($extendedReflection->getConstant('name'));//Extended

/**
 * From Objects
 */
$main = new MainClass();
$extended = new ExtendedClass();

//get reflection of main class
$mainReflection = new ReflectionObject($main);

if($mainReflection->hasConstant('name'))
    var_dump($mainReflection->getConstant('name'));//Primary

//get reflection of extended class
$extendedReflection = new ReflectionObject($extended);

if($extendedReflection->hasConstant('name'))
    var_dump($extendedReflection->getConstant('name'));//Extended

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