1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Php 接口能定义常量 关于php:接口常量的优点和缺点

Php 接口能定义常量 关于php:接口常量的优点和缺点

时间:2022-05-28 12:09:58

相关推荐

Php 接口能定义常量 关于php:接口常量的优点和缺点

PHP接口允许在接口中定义常量,例如

interface FooBar

{

const FOO = 1;

const BAR = 2;

}

echo FooBar::FOO; // 1

任何实现类都会自动提供这些常量,例如

class MyFooBar implement FooBar

{

}

echo MyFooBar::FOO; // 1

我个人认为,全球都是邪恶的。但是我想知道接口常数是否也一样。鉴于一般认为对接口进行编码是一种好习惯,使用接口常量是否是在类上下文之外可以接受的唯一常量?

尽管我很好奇您的个人意见以及是否使用接口常量,但我主要是在寻找答案的客观原因。我不希望这成为投票类型的问题。我对使用接口常量对可维护性有什么影响很感兴趣。耦合。或单元测试。它与SOLID PHP有何关系?它违反任何被认为是PHP良好实践的编码原则吗?你明白了...

注意:Java也有一个类似的问题,其中列出了一些非常好的理由来说明它们是"不良实践"的原因,但是由于Java不是PHP,因此我有理由再次在PHP标签中提出问题。

嗯,我以前从未遇到过在接口中定义常量的需求。 值得一提的是,实现该接口的类不能覆盖常量,而仅相互扩展的类可以覆盖常量。

我相信常数也不错,因为即使我们关注单元可测试性,它们也具有可预测的值。 全局变量是邪恶的,因为任何人都可以更改它,因为它是一个变量并且所有内容都具有作用域,但常量永远不会更改其值,因此,术语"常量"。

好吧,我认为这归结为好与好之间的区别。

虽然在大多数情况下,可以通过实现其他模式(策略或轻量级)来避免使用常量,但是可以说不需要用其他六类来表示一个概念。我认为其归结为需要其他常量的可能性。换句话说,需要扩展接口上的常量所提供的ENUM。如果可以预见需要扩展它,那么可以使用更正式的模式。如果不是,那么就足够了(足够好了,因此编写和测试的代码更少了)。这是一个足够好和不好使用的示例:

坏:

interface User {

const TYPE_ADMINISTRATOR = 1;

const TYPE_USER= 2;

const TYPE_GUEST= 3;

}

够好了:

interface HTTPRequest_1_1 {

const TYPE_CONNECT = 'connect';

const TYPE_DELETE = 'delete';

const TYPE_GET = 'get';

const TYPE_HEAD = 'head';

const TYPE_OPTIONS = 'options';

const TYPE_POST = 'post';

const TYPE_PUT = 'put';

public function getType();

}

现在,我选择这些示例的原因很简单。 User接口正在定义用户类型的枚举。随着时间的流逝,这很可能会扩展,并且更适合于其他模式。但是HTTPRequest_1_1是一个不错的用例,因为枚举是由RFC2616定义的,并且在类的生存期内不会更改。

总的来说,我不认为常量和类常量的问题是一个全局问题。我将其视为依赖性问题。这是一个狭窄的区别,但却是一个明确的区别。我认为全局问题就像未强制执行的全局变量一样,因此会产生软的全局依赖关系。但是硬编码的类会创建强制的依赖关系,因此会创建硬的全局依赖关系。因此,两者都是依赖关系。但是我认为全局会更糟糕,因为它没有被强制执行。这就是为什么我不喜欢将类依赖与全局依赖放在一起。

如果编写MyClass::FOO,则将硬编码到MyClass的实现细节。这会产生硬耦合,从而使代码的灵活性降低,因此应避免使用。但是,存在接口以完全允许这种类型的耦合。因此MyInterface::FOO不会引入任何具体的耦合。话虽如此,我不会仅仅为了向接口添加常量而引入接口。

因此,如果您正在使用接口,并且非常确定自己(或其他任何人)不需要其他值,那么我就不会真正看到接口常数有什么大问题了……最好设计将不包含任何常量或条件,幻数,幻弦或硬编码的任何内容。但是,这会增加开发时间,因为您必须考虑其用途。我的观点是,多数时候绝对值得花额外的时间来构建出色的实体设计。但是有时候确实足够好是可以接受的(需要有经验的开发人员来了解差异),在那种情况下就可以了。

再次,那只是我的看法...

在这种情况下,您会建议用户采取什么其他模式?

@Jacob:我会把它抽象化。根据您的需求,Id可能会构建一个Access类,该类将从数据库表中获取其数据。这样,添加新级别就像插入新行一样容易。另一种选择是建立一个ENUM类集(每个权限角色都有一个类)。然后,您可以在必要时扩展类以提供适当的权限。但是还有其他方法也可以使用

非常扎实和明确的答案! +1

具有公共常量的类不应具有任何方法。它应该只是数据结构或对象,而不是两者。

@OZ_:好吧,这取决于使用情况。如果您要构建ENUM样式类,则应具有与强制执行约束有关的方法(例如SPLEnum)。如果您不这样做,而您只是表示一个可能改变的值的域(以消除幻数和字符串),那么无论是否仅是类,它都将悬而未决。它实际上取决于类和常量的原因。所以不,我不同意带有公共常量的类不应该有方法。我通常会把它们放在一个接口上,但这取决于

"最好的设计不会包含任何常数或条件,幻数或幻弦或硬编码的任何东西。" - 这听起来很不错。您如何避免有条件的决定,这是任何决策过程的核心?

@FrederikKrautwald:您可以避免多态的条件(在大多数情况下):查看此答案以及观看此清洁代码讲座...

@ircmaxell,感谢您的链接。我同意通过重构条件,在大多数情况下可以消除条件。但是,我看不到如何完全避免它们,但这也许只是我缺乏逻辑。

@FrederikKrautwald,您无法完全避免它们。您可以在业务逻辑中完全避免它们。在工厂,制造商和配置逻辑中,它们仍然是必需的,但是实际的"业务工作"可以是完全有条件的……我不是说应该是完全免费的,但是可以。

@ircmaxell,很好。这也是我得出的结论,我不会再为解决如何删除所有和一个问题而费劲。

@ircmaxell我有两个问题:1."最好的设计不会包含任何常量..."那么当拥有10个具有相同字符串的文件时,您将如何管理,您是否要进行单点更改? 2."实际的"业务工作"可以是完全无条件的.."您是否将核心域称为业务工作(实体/价值对象等)。如果是这样,您是否建议使用数组等?如果是这样,我们如何实现规格和验证器?

我认为通常最好将常量(特别是枚举常量)作为接口中的单独类型("类")来处理:

define(TYPE_CONNECT, 'connect');

define(TYPE_DELETE , 'delete');

define(TYPE_GET , 'get');

define(TYPE_HEAD , 'head');

define(TYPE_OPTIONS, 'options');

define(TYPE_POST , 'post');

define(TYPE_PUT , 'put');

interface IFoo

{

function /* int */ readSomething();

function /* void */ ExecuteSomething(/* int */ param);

}

class CBar implements IFoo

{

function /* int */ readSomething() { ...}

function /* void */ ExecuteSomething(/* int */ param) { ... }

}

或者,如果您想使用一个类作为名称空间:

class TypeHTTP_Enums

{

const TYPE_CONNECT = 'connect';

const TYPE_DELETE = 'delete';

const TYPE_GET = 'get';

const TYPE_HEAD = 'head';

const TYPE_OPTIONS = 'options';

const TYPE_POST = 'post';

const TYPE_PUT = 'put';

}

interface IFoo

{

function /* int */ readSomething();

function /* void */ ExecuteSomething(/* int */ param);

}

class CBar implements IFoo

{

function /* int */ readSomething() { ...}

function /* void */ ExecuteSomething(/* int */ param) { ... }

}

并不是说您仅使用常量,而是使用枚举值或枚举的概念,这些枚举值或枚举被认为是具有特定用法("域"?)的特定类型。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。