PHP 特征 - 定义通用常量
Posted
技术标签:
【中文标题】PHP 特征 - 定义通用常量【英文标题】:PHP traits - defining generic constants 【发布时间】:2014-08-13 00:35:31 【问题描述】:定义可以被命名空间中的多个类使用的常量的最佳方法是什么?我试图避免过多的继承,所以扩展基类不是一个理想的解决方案,我正在努力寻找一个使用特征的好的解决方案。这在 php 5.4 中是否有可能,还是应该采取不同的方法?
我有以下情况:
trait Base
// Generic functions
class A
use Base;
class B
use Base;
问题是无法在 PHP 特征中定义常量。理想情况下,我想要以下内容:
trait Base
const SOME_CONST = 'someconst';
const SOME_OTHER_CONST = 'someotherconst';
// Generic functions
然后可以通过应用 trait 的类访问这些:
echo A::SOME_CONST;
echo B::SOME_OTHER_CONST;
但是由于特征的限制,这是不可能的。有什么想法吗?
【问题讨论】:
你可以使用静态属性,它不是一个常量,但在调用它时也只有一个字符不同...public static $SOME_VAR = 'someconst';
和echo B::$SOME_VAR
感谢您的提示。这是一种选择,尽管这是一项重构工作,而不是新代码,所以我更希望行为保持不变而不是更新所有常量调用(有很多)。
你可以使用接口来声明常量。
bugs.php.net/bug.php?id=70986
bugs.php.net/bug.php?id=70986 现在已被bugs.php.net/bug.php?id=75060 取代
【参考方案1】:
我最终使用了user sectus's suggestion 的接口,因为这感觉是处理这个问题的最少问题的方式。使用接口来存储常量而不是 API 契约有一种不好的味道,所以这个问题可能更多是关于 OO 设计而不是 trait 实现。
interface Definition
const SOME_CONST = 'someconst';
const SOME_OTHER_CONST = 'someotherconst';
trait Base
// Generic functions
class A implements Definition
use Base;
class B implements Definition
use Base;
这允许:
A::SOME_CONST;
B::SOME_CONST;
【讨论】:
所以接口可以有常量...但特征不能? PHP 变得越来越奇怪了。 @Adambean 覆盖一个常量违背了constant
的目的,它并不意味着改变。
然而,如果我想在 trait 的代码实现中使用一个值,这是不可能的。
@Aknosis 我个人认为它不仅仅是一个常数在其生命周期内不会改变价值。这并不意味着在扩展类时不能用另一个值重新定义它(并使用 [例如] static::VALIDATION_REGEX
来获取 late-static-bound 值)
PHP '错误'#75060【参考方案2】:
您也可以使用静态变量。它们可以在类或特征本身中使用。 - 作为 const 的替代品,对我来说效果很好。
trait myTrait
static $someVarA = "my specific content";
static $someVarB = "my second specific content";
class myCustomClass
use myTrait;
public function hello()
return self::$someVarA;
【讨论】:
我知道这是旧的,但你不想用 const 来改变值吗? 你不能在 Trait 中使用常量。【参考方案3】:要限制常量的范围,您可以在命名空间中定义它们:
namespace Test;
const Foo = 123;
// generic functions or classes
echo Foo;
echo namespace\Foo;
这种方法的一个缺点是自动加载对常量不起作用,至少对 5.4 不起作用;解决这个问题的典型方法是将这些常量包装在一个静态类中,即:
namespace Test;
class Bar
const Foo = 123;
【讨论】:
有趣的想法。我没有意识到您可以直接访问命名空间常量。问题是这个库是 PSR-0 自动加载的,所以我担心这种方法行不通。不过感谢您的回答。 @orciny 好吧,如果将这些常量包装在静态类中,自动加载将起作用;不是最漂亮的代码的最闪亮的例子,但它会工作:)【参考方案4】:不是很好,但也许...
trait Base
public static function SOME_CONST()
return 'value1';
public static function SOME_OTHER_CONST()
return 'value2';
// generic functions
class A
use Base;
class B
use Base;
echo A::SOME_CONST();
echo B::SOME_OTHER_CONST();
【讨论】:
请注意那些没有遵循的人,这些是静态方法,而不是常量。虽然使用时它们看起来有点像常量。如果您要这样做并且希望这些方法的行为更像常量,则需要在方法前加上关键字final
以确保它们不会被覆盖(与常量相同的行为)。
@John Hunt, final
不适用于特质,请参阅 ***.com/a/33481511/251735【参考方案5】:
从 PHP 8.1 开始,可以在特征中使用 readonly
属性。
<?php
trait A
public readonly int $variable;
protected function initA(int $newValue)
$this->variable = $newValue;
public function changeVariable(int $newValue)
$this->variable = $newValue;
class B
use A;
public function __construct()
$this->initA(1);
$b = new B();
$b->changeVariable(5); // should faild: Fatal error: Uncaught Error: Cannot modify readonly property B::$variable
【讨论】:
【参考方案6】:另外需要考虑的是你是否可以使用抽象类来代替,然后继承。
abstract class Base
const A = 1;
const B = 2;
class Class1 extends Base
class Class2 extends Base
echo Class1::A;
echo Class2::B;
当然,trait 的部分原因是用组合替换复杂的继承树。视情况而定。
【讨论】:
以上是关于PHP 特征 - 定义通用常量的主要内容,如果未能解决你的问题,请参考以下文章