我注意到从PHP5开始,接口已添加到该语言中。但是,由于PHP的类型过于宽松,因此似乎失去了使用接口的大多数好处。为什么这包括在语言中?
我注意到从PHP5开始,接口已添加到该语言中。但是,由于PHP的类型过于宽松,因此似乎失去了使用接口的大多数好处。为什么这包括在语言中?
Answers:
PHP接口的主要优点是类可以实现多个接口。这使您可以对共享某些功能但不必共享父类的类进行分组。一些示例可能包括以某种方式缓存,输出或访问类的属性。
在您的代码中,您可以检查类是否实现了给定的接口,而不必检查类名。然后,添加新类后,您的代码仍然可以使用。
PHP提供了一些可以在各种情况下派上用场的预定义接口:http : //php.net/manual/en/reserved.interfaces.php。
编辑-添加示例
如果您有一个名为MyInterface的接口,并且正在使用不同类的多个对象,这些对象可能会或可能不会共享某些功能,则接口可以使您执行以下操作:
// Assume $objects is an array of instances of various classes
foreach($objects as $obj) {
if($obj instanceof MyInterface) {
$obj->a();
$obj->b();
$obj->c();
}
}
PHP是松散类型的,但对于诸如方法参数之类的东西,可以强类型化。
考虑以下示例:
interface Car { function go(); }
class Porsche { function go() {} }
function drive(Car $car) {}
$porsche = new Porsche();
drive($porsche);
上面的代码将输出:
传递给drive()的参数1必须实现接口Car,保时捷实例已给定
null
为参数设置默认值。
drive
需要Car
,那么null
无论如何传递并不会很有帮助...
function addView($name, Template $template, SecurityMode $securityMode = null, $methodName = null);
您可能有一个,$methodName
但没有$securityMode
。
接口使您可以实现开闭原理,维护松散耦合的代码库以及实现许多最佳的OOP设计模式。
例如,如果一个类接受另一个类作为参数:
class A {
public function __construct(B $class_b) {
// use class b
$class_b->run();
}
}
现在,您的A类和B类紧密耦合,并且A类不能使用除B类之外的任何其他类。类型提示可确保您具有正确的参数类型,但现在巩固了A和B之间的关系。
假设您希望类A能够使用所有具有run()方法的类。这基本上是(但不是完全)COMMAND设计模式。要解决此问题,您可以使用接口而不是具体的类来键入提示。B将实现该接口,并将其作为类A的参数接受。这样,类A可以接受使用该接口作为其构造函数参数的任何类。
大多数OOP设计模式都使用这种类型的编码,并且可以在以后的某个时间更轻松地更改代码。这些是AGILE编程基础知识的一部分。
@pjskeptic有一个很好的答案,而@KamilTomšík对这个答案有很好的评论。
关于动态类型化语言(如PHP)的妙处在于,您可以尝试在对象上使用方法,除非该方法不存在,否则它不会对您大喊大叫。
像PHP这样的动态类型化语言的问题在于,您可以尝试在对象上使用方法,当方法不存在时,它会大喊大叫。
接口增加了一种方便的方法来调用未知对象上的方法,并确定方法是否存在(不一定是正确的或不会起作用的)。它不是语言的必要部分,但是它使编码更加方便。它允许强类型的OOP开发人员编写强类型的PHP代码,然后可以与其他PHP开发人员编写的松类型的PHP代码一起使用。
类似的功能:
foo( IBar $bar )
{
$baz = $bar->baz();
...
}
比:
foo( $bar )
{
if ( method_exists( $bar, 'baz' ) )
{
$baz = $bar->baz();
}
else
{
throw new Exception('OMGWTF NO BAZ IN BAR!');
}
...
}
恕我直言,简单易读的代码是更好的代码。
如果您使用的是鸭式打字机,它们是完全没有用的,实际上,当您进行鸭式打字时,使用使用任何类型提示的库/框架会很烦人。
这也适用于各种动态元编程(魔术方法)。
PHP 不是宽松或强壮的,而是动态类型的。
关于接口,您应该问自己的第一件事是:接口的最大好处是什么?
在OOP中,接口不仅与类型有关,而且与行为有关。
由于PHP还具有类型提示功能,因此您可以像使用纯oo语言(例如Java)一样使用接口。
interface File
{
public function getLines();
}
CSVFile implements File
{
public function getLines()
{}
}
XMLFile implements File
{
public function getLines()
{}
}
JSONFile implements File
{
public function getLines()
{}
}
class FileReader
{
public function read(File $file)
{
foreach($file->getLines() as $line)
{
// do something
}
}
}
使用PHP接口实现,您还可以使用PHPUnit为抽象类创建模拟 -这真是个特性:
public function testSomething()
{
$mock = $this->getMockForAbstractClass('File');
$mock->expects($this->once())
->method('getLines')
->will($this->returnValue(array()));
// do your assertions
}
因此,基本上,您可以使用语言功能(其中之一是接口)来在PHP中使用SOLID兼容的应用程序。
接口对依赖项注入的作用远比具体的有用。作为一个简单的例子:
interface Istore {
public function save();
}
class Article_DB implements Istore
{
public function save($data)
{
// do save to format needed.
}
}
class Article
{
private $content;
public function content($content)
{
$this->content = $content;
}
public function save(Istore $store)
{
$store->save($this->content);
}
}
$article = new Article();
$article->content('Some content');
$store = new Article_DB();
$article->save($store);
现在说一下,如果您的需求发生变化,并且想要保存为pdf。您可以为此目的创建一个新类,而不用污染Article类。
class Article_PDF implements Istore
{
public function save($data)
{
// do save to format needed.
}
}
$article = new Article();
$article->content('Some content');
$store = new Article_PDF();
$article->save($store);
现在,Article类具有一个合同,用于保存的类必须实现Istore接口。它不在乎其保存位置或保存方式。
很多人可能会讨厌我以这种方式回答问题,但是使用PHP可以轻松解决输入问题的解决方案。是的, PHP是松散类型的,因此默认情况下采用类型,这会引起一些问题,尤其是在比较操作中,这是大多数人的问题。话虽这么说,如果将使用的内容转换为所需的类型,然后使用按位比较运算符,PHP可以与任何强类型语言一样严格。这是我能想到的最简单的示例:
$ myVar =(int)0; $ myOtherVar ='0';
比较($ myVar == $ myVar)等于(布尔)true
但是比较($ myVar === $ myVar)等于(bool)false,就像任何“类型化”比较一样
我真的希望开发人员不要再争论这些事情,如果您对PHP的工作方式有疑问,要么在Java中运行程序,然后开始生存,要么以其实现您想要的方式使用它。反正它对你有什么好处?给你借口整天缠着吗?使你看起来比别人好吗?好吧,您对自己感到如此高度,以至于愿意让别人看起来很糟,但实际上,这是您的偏好,并强迫您相信任何人,实际上只会使他们以不适应导致三件事的方式进行编码:
1)他们将按照您的方式进行编码,但是按照您的标准“混乱”(想想,您是否见过Java程序员创建了他们的第一个PHP程序,反之亦然?这与改变他们的方法论一样,甚至更糟。)
2)您会发现其他值得抱怨的地方
3)它们可能需要更长的时间才能生产。也许这会使您在短期内看起来更好,但是整个团队的情况会更糟(请记住,您的编码可能比其他人慢,并且只要团队在合理的时间范围内满足可交付成果,这并不一定很糟糕,但是将您的习惯强加给通常表现得更快的人,可能最终会使您的整个团队变慢,因此,在非常苛刻的工作流程中看起来更糟)
我个人更喜欢编写过程PHP代码,尽管我可以并且已经使用OOP以几种不同的语言编写了完整的程序。话虽这么说,我已经看到了好的OOP代码和不好的OOP代码,以及好的过程代码和不好的过程代码……确实与实践无关,但与您所使用的习惯有关,即使如此,很多事情是我的解释……这并不意味着我要对那些开发人员说不好,也不要说“我的方法是最好的” BS吹牛,这对我来说是正确的,而且我工作的公司很漂亮我为自己的工作感到高兴,对此我感到自豪。有理由应该建立一个标准,但是您选择的标准中包含的内容非常重要...感谢您让我从中脱颖而出。祝你有美好的一天。
示例:您需要缓存数据。怎么样?缓存有很多不同的引擎,哪个是最好的?谁在乎您是否拥有抽象层,该抽象层具有一些ICacheDriver接口以及一组诸如key,get,put,clear等方法。只需对其实施当前项目中需要的内容,并在需要时进行更改即可。还是toString的简单用法。您有一组不同的可显示对象。您只需实现Stringable接口(它描述了toString方法[[在PHP中没有真正的接口,例如,]]),然后使用(string)$ obj遍历所有对象。除了切换(true),您还需要做所有事情。{case $ obj nottanceof A1:“ do 1”; 打破; ...}
简单。因此,毫无疑问“为什么?”。有“如何更好地利用它?”。;-) 祝好运。
我猜。
PHP被许多入门级程序员使用,入门级程序员在大学里被教过Java。
在他们的101编程课程之后,他们开始na他们想要Java功能的Zend,因为那是他们被认为思考的方式,以您自己的方式思考(或理解鸭子的打字)很难,而您只有20岁。
Zend务实,添加功能比假装它们始终容易得多。
这也吸引了更多的用户,而不是让他们离开,所以这一定是好的。
此过程的另一个实例?刚接触.NET和Java课程的人们也希望使用基础类框架,他们对此na不已,直到Zend发芽Zend框架。这会吸引更多的用户。等等……
(多年来,PHP团队一直在与之抗争的唯一语言功能是goto
)
PHP12
可能具有世界上所有的语法功能(我希望它不会有一个抽象层运行时,很难,因为那是杀死perl的原因),并且对功能和数据类型范例有所了解,但仍然没有goto
。