
当类实现接口时,所有 public 方法的参数列表(数量、类型、顺序)必须与接口中完全一致,否则会触发“Method is not compatible”错误。本文详解根本原因、修复步骤及最佳实践。
当类实现接口时,所有 public 方法的参数列表(数量、类型、顺序)必须与接口中完全一致,否则会触发“method is not compatible”错误。本文详解根本原因、修复步骤及最佳实践。
在 PHP 中,接口(interface)定义的是契约(contract):它强制规定了实现类必须提供哪些方法,以及这些方法的精确签名——包括返回类型、参数数量、参数类型(PHP 7.4+ 支持参数类型声明)和参数名称(虽不参与类型检查,但 IDE 和静态分析工具如 Intelephense 会校验一致性)。你遇到的错误:
Method 'Calculator::getNpsScore()' is not compatible with method 'NpsCalculatorContract::getNpsScore()'
根本原因在于:接口中 getNpsScore() 声明为无参方法(public function getNpsScore(): int;),而你在 Calculator 类中却实现了带三个参数的版本(getNpsScore($promoters, $detractors, $responses))。PHP 的 LSP(里氏替换原则)要求子类方法签名必须与父接口/父类保持协变兼容,参数只能减少(通过默认值),不能增加或改变类型;反之,增加参数属于逆变(contravariance),直接违反契约。
✅ 正确修复方案:统一签名,复用内部状态
接口方法不应重复传入 $responses 等数据——它们已在构造时注入,应作为类属性复用。修改核心逻辑如下:
-
修正接口方法签名:所有 getter 方法不接收参数,仅依赖
$this->responses; -
修正类实现:移除所有方法的冗余参数,改用
$this->responses; -
补全构造函数类型提示:
__construct(array $responses)并赋值给属性; -
添加属性声明(推荐):明确
$responses类型,提升可读性与 IDE 支持。
✅ 修复后的完整代码:
<?php interface NpsCalculatorContract
{
public function __construct(array $responses);
public function getNpsScore(): int;
public function getAverageScore(): float;
public function getPromoterCount(): int;
public function getPassiveCount(): int;
public function getDetractorCount(): int;
public function getTotalResponseCount(): int;
}
class Calculator implements NpsCalculatorContract
{
private array $responses;
public function __construct(array $responses)
{
$this->responses = $responses;
}
public function getNpsScore(): int
{
$promoters = $this->getPromoterCount();
$detractors = $this->getDetractorCount();
$total = $this->getTotalResponseCount();
if ($total === 0) {
return 0;
}
$score = (($promoters - $detractors) / $total) * 100;
return (int) round($score); // 符合接口注释“rounded to nearest integer”
}
public function getAverageScore(): float
{
if (empty($this->responses)) {
return 0.0;
}
return round(array_sum($this->responses) / count($this->responses), 1);
}
public function getPromoterCount(): int
{
return count(array_filter($this->responses, fn($v) => $v === 9));
}
public function getPassiveCount(): int
{
return count(array_filter($this->responses, fn($v) => $v === 7 || $v === 8));
}
public function getDetractorCount(): int
{
return count(array_filter($this->responses, fn($v) => $v responses);
}
}
⚠️ 关键注意事项
- 不要在接口中为 getter 添加参数:这违背封装原则,也破坏了“一次注入、多次使用”的设计意图;
-
构造函数必须匹配接口声明:
public function __construct(array $responses)—— 注意array类型提示不可省略; -
空数组安全处理:在
getNpsScore()和getAverageScore()中添加if (empty(...))防止除零错误; -
round()与类型转换:getNpsScore()返回int,需显式round()后(int)转换,确保符合: int声明; -
避免
global或外部变量:如问题中尝试的global $responses,这会破坏面向对象设计,且无法解决签名不匹配问题。
✅ 验证示例
$responses = [9, 9, 7, 5, 10, 8, 4, 9];
$calc = new Calculator($responses);
echo "NPS: {$calc->getNpsScore()}\n"; // e.g., 25
echo "Avg: {$calc->getAverageScore()}\n"; // e.g., 7.6
echo "Promoters: {$calc->getPromoterCount()}\n"; // 3
遵循以上规范,即可彻底消除 “Method is not compatible” 错误,并构建出类型安全、可维护的 NPS 计算器组件。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











