PHP 类型提示无法与接口和抽象类相处?
我认为在代码示例中看到问题比首先编写问题要容易得多。这是我的 php 代码:
<?php
interface AnInterface
{
public function method();
}
class AClass implements AnInterface
{
public function method()
{
echo __METHOD__;
}
}
abstract class AnAbstractClass
{
abstract public function method( AnInterface $Object );
}
class ConcreteClass extends AnAbstractClass
{
public function method( AClass $Object )
{
$Object->method();
}
}
$Object1 = new ConcreteClass();
$Object2 = new AClass();
$Object1->method( $Object2 );
上面的代码导致以下错误:
致命错误:ConcreteClass::method() 的声明必须与 AnAbstractClass::method() 的声明兼容
问题是 php 似乎无法将 AnAbstractClass::method 和 ConcreteClass::method 的签名识别为兼容。我做错了什么吗?谢谢!
I think it'll be much easier to see the problem in a code example than writing the question in the first place. Here is my php code:
<?php
interface AnInterface
{
public function method();
}
class AClass implements AnInterface
{
public function method()
{
echo __METHOD__;
}
}
abstract class AnAbstractClass
{
abstract public function method( AnInterface $Object );
}
class ConcreteClass extends AnAbstractClass
{
public function method( AClass $Object )
{
$Object->method();
}
}
$Object1 = new ConcreteClass();
$Object2 = new AClass();
$Object1->method( $Object2 );
The above code causes the following error:
Fatal error: Declaration of ConcreteClass::method() must be compatible with that of AnAbstractClass::method()
The problem is that php doesn't seem to be recognizing the signatures of AnAbstractClass::method and ConcreteClass::method as compatible. Am I doing something wrong? Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
PHP 是正确的,它们不兼容。通过仅允许将
AClass
(或其子级)的实例传递给ConcreteClass::method
,您就违反了AnAbstractClass
提供的约定:它的任何子类都必须接受AnInterface
作为其method()
的参数。如果您的示例有效,并且我有另一个类
BClass
实现AnInterface
,我们会遇到一种情况,根据AnAbstractClass
,method ()
应该接受BClass
的实例,而根据ConcreteClass
,它不应该接受。更改
ConcreteClass::method
的签名以匹配AnAbstractClass::method
的签名。PHP is correct, they're not compatible. By allowing only instances of
AClass
(or its children) to be passed toConcreteClass::method
, you're breaking the contract thatAnAbstractClass
provides: Any of its subclasses must acceptAnInterface
as an argument to itsmethod()
.If your example worked, and I had another class
BClass
implementingAnInterface
, we'd have a situation where according toAnAbstractClass
,method()
should accept instances ofBClass
, while according toConcreteClass
, it shouldn't.Change your signature for
ConcreteClass::method
to match that ofAnAbstractClass::method
.下面是一个示例,说明为什么不允许这样做:
这将是一个有效的代码,但如果您将
ConcreteClass
传递给 moo,它会失败,因为它的方法ConcreteClass::method< /code> 不允许
BClass
。虽然很复杂,但是如果你看个例子就更容易理解了。
Here's an example that shows, why this is not allowed:
This would be a valid code, but it would fail, if you pass a
ConcreteClass
to moo, because its methodConcreteClass::method
does not allowBClass
.It is complicated, but it is easier to understand, if you see an example.
不会计算。昨天我们进行了同样的讨论:
参数类型可以专门用于 PHP
所有派生的类必须以相同的方式实现方法签名。
理想情况下,这是在运行时检查的事情。但在 PHP 中,解析器会这样做。 (作为补偿,PHP 在解析时不会检查私有/受保护的属性访问,而是让其在运行时爆炸。)
如果您想强制执行更严格的类型,我建议:
Does not compute. We had the same discussion yesterday:
Can parameter types be specialized in PHP
All your derived classes must implement the method signatures identically.
This is something that would ideally be checked at runtime. But in PHP the parser does. (To compensate, PHP does not check private/protected attribute access at parsing time, but let that one rather blow up at runtime.)
If you want to enforce a more stringent type, I would advise: