使用 psalm 扩展接口的泛型

Posted

技术标签:

【中文标题】使用 psalm 扩展接口的泛型【英文标题】:Extend a generic of an interface using psalm 【发布时间】:2021-08-28 02:16:10 【问题描述】:

我已经习惯使用 psalm,但我遇到了一个问题。我已经在 C# 中有这个结构,它对我有用。我真的不明白如何使用 psalm 解决这个问题。

我有一个 ContextInterface 和另一个实现它。

interface ContextInterface  public function getProductId(): int; 
interface SingleContextInterface extends ContextInterface  public function getWidth(): int; 

此外,我还有他们的策略界面。

/**
 * @template-covariant T as ContextInterface
 * @psalm-immutable
 */
interface CalculatorInterface

    /**
     * @psalm-param T $context
     */
    public function getPrice(ContextInterface $context): int;


/**
 * @template T as SingleContextInterface
 * @template-extends CalculatorInterface<T>
 * @psalm-immutable
 */
interface SingleDimensionalPriceCalculator extends CalculatorInterface  

还有一个实现接口的类:

/**
 * @template T as SingleContextInterface
 * @template-implements SingleDimensionalPriceCalculator<T>
 * @psalm-immutable
 */
class SingleDimensionCalculator implements SingleDimensionalPriceCalculator

    /**
     * @psalm-param SingleContextInterface $context
     */ 
    public function getPrice(ContextInterface $context): int
    
        $context->getWidth();
        return 1;
    
    

对于getWidth() 方法调用,我收到以下错误:

ERROR: ImpureMethodCall - 37:19 - Cannot call an possibly-mutating method SingleContextInterface::getWidth from a mutation-free context

psalm.dev上的例子

当然真实案例更复杂,包含更多接口。

【问题讨论】:

【参考方案1】:

我想,问题在于我将CalculatorInterface 上的模板标记为协变。我可以在没有协变的情况下扩展它。

psalm.dev 上的示例

【讨论】:

您还删除了@immutable,因此您不会再遇到可变性错误是很自然的 SingleContextInterface 上添加@psalm-immutable 可以解决这个问题,因为它会将getWidth() 标记为纯。

以上是关于使用 psalm 扩展接口的泛型的主要内容,如果未能解决你的问题,请参考以下文章

java中的泛型

Java的泛型---(英雄联盟集合嵌套案例)

java泛型泛型的内部原理:类型擦除以及类型擦除带来的问题

Java基础——Java中的泛型(值得一看)

夯实Java基础系列13:深入理解Java中的泛型

java的泛型