在 PHP 中使用类常量和覆盖

Posted

技术标签:

【中文标题】在 PHP 中使用类常量和覆盖【英文标题】:Using class constants and overriding in PHP 【发布时间】:2012-04-14 07:06:22 【问题描述】:

如果我有一个值可以为真或假的类结构,它不会改变,目前实现为变量最好将它们更改为常量,例如:

class Parent 
    const BOOL_CONST = false;

    ...


class SomeChild extends Parent 
    const BOOL_CONST = true;

    ...

稍后我有一个对象,它可能是该类层次结构中的任何类型,无论是父对象还是其子对象之一,并且某些子对象可能(例如“SomeChild”)已将值重载为真。

有什么方法可以在不知道类的情况下访问常量吗?换句话说,我可以这样做:

$object->BOOL_CONST

或者将这些值保留为变量会更好,即使它们确实不应该改变?

更新

我已经改写了我上面的问题,以更好地表达我想要问的内容。

【问题讨论】:

Can I get CONST's defined on a php class? 的可能重复项 @JuicyScripter 我自己看不到相似之处吗?我想我的问题与需要在对象级别获取不应更改但不知道类名的值有关。目前这些是作为变量实现的,但我的某些部分认为它们应该是常量。但看起来那样做会破坏很多东西。 【参考方案1】:

使用双冒号::: 访问常量

Parent::BOOL_CONST

SomeChild::BOOL_CONST

within the class
parent::BOOL_CONST  
self::BOOL_CONST

【讨论】:

+1 谢谢。我想我真的应该将这些值作为变量保留,即使它们不应该改变。我需要从课堂外访问它们。 如上所示,它们是:ClassName::CONST 是的,但这只有在我知道类名的情况下才有效。如果对象可以是一组类中的一个,那我真的做不到。【参考方案2】:

不,您不能从对象上下文中访问常量,但是您可以使用反射来获取 $object 的类,然后使用 :: 来获取 BOOL_CONST。所以:

$class = get_class($object);
$class::BOOL_CONST;

好的,不,这不是技术上的反思。另外,我不能 100% 确定 $class:: 是否会正确解析。如果上述方法不起作用,请使用实际的 ReflectionClass 类。

【讨论】:

+1 虽然我怀疑使用 ReflectionClass 对于我的目的来说可能是矫枉过正。我可能最好将这些值保留为变量,而不是仅仅因为它们不应该改变而将它们整理成常量。 我同意;通常优先考虑速度而不是清洁(我经常这样做),ReflectionClass 是一个缓慢的庞然大物。【参考方案3】:

您不能使用$object->BOOL_CONST,因为必须静态调用类常量 (SomeChild::BOOLCONSTANT)。

但是,也许您可​​以尝试类似的方法: // 编辑:这行得通 :)

$class = get_class($object);
$const = $class::BOOL_CONST;

【讨论】:

【参考方案4】:

有什么方法可以在不知道类的情况下访问常量吗? 换句话说,我可以这样做:

是的,为了引用一个常量,您需要使用以下结构:

self::NAME_OF_CONSTANT:给我一个在这个类中定义的常量;如果我不定义它,请从我的父母那里得到它 static::NAME_OF_CONSTANT:只给我一个在这个类中定义的常量;永远不要向我父母求助 parent::NAME_OF_CONSTANT:只给我一个在我的父类中定义的常量;永远不要自己找它

顺便说一句,您使用了“重载”一词;但是,我相信您的意思是说“被覆盖”。重载在面向对象语言中具有不同的语义。

【讨论】:

谢谢。你对我承认“重载”和“压倒一切”的说法是对的。我将编辑问题以使用正确的术语。【参考方案5】:

PHP 5.3 现在接受对象作为类引用:$this::BOOL_CONST 现在被接受。

//
// http://php.net/manual/en/language.oop5.constants.php
//
// As of PHP 5.3.0, it's possible to
// reference the class using a variable.
// The variable's value can not be a keyword
// (e.g. self, parent and static). 
//

// I renamed "Parent" class name to "constantes"
// because the classname "Parent" can be confused with "parent::" scope
class constantes

    const  test                     = false;


// I renamed "SomeChild" too, with no reason...
class OverloadConst extends constantes

    const test                      = true;
    public function waysToGetTheConstant()
    
        var_dump(array('$this'=>$this::test));    // true, also usable outside the class
        var_dump(array('self::'=>self::test));    // true, only usable inside the class
        var_dump(array('parent::'=>parent::test));    // false, only usable inside the class
        var_dump(array('static::'=>static::test));    // true, should be in class's static methods, see http://php.net/manual/en/language.oop5.late-static-bindings.php
    


// Classic way: use the class name
var_dump(array('Using classname'    => OverloadConst::test));

// PHP 5.3 way: use the object
$object = new OverloadConst();
var_dump(array('Using object'       => $object::test));
$object->waysToGetTheConstant();

请注意,您可以覆盖类常量,但不能覆盖接口常量。 如果constantesOverloadConsts 实现的接口,则不能覆盖其const test(或BOOL_CONST)。

来源

PHP 5.3 中的常量:http://php.net/manual/en/language.oop5.constants.php 后期静态绑定:http://php.net/manual/en/language.oop5.late-static-bindings.php

【讨论】:

以上是关于在 PHP 中使用类常量和覆盖的主要内容,如果未能解决你的问题,请参考以下文章

php--在类中声明常量的关键字

从 Makefile 覆盖宏常量

PHP面向对象编程

在angularJS中覆盖模块值/常量的最佳方法

PHP新手之学习类与对象

是否可以在测试中覆盖模块配置函数的常量?