`instanceof` 运算符是否违反了 Liskov 替换原则?

3
例如我有货币(Currency)交换(Exchange),涉及到各种关于货币(Currency)的实现。我想为某些货币添加额外汇率时,可以这样做:
interface Currency { double rate();}
interface Exchange { double convert(Currency currency, double money); }
class PrivateBank implements Exchange {
    @Override
    public double convert(Currency currency, double money) {
        double extra_rate = 1.0;
        if (currency instanceof CanadaDollar) { /// ?
            extra_rate = 1.05;
        }
        return money * currency.rate() * extra_rate;
    }
}

这里是否违反了LSP原则?

3个回答

1
不会,因为任何实现了 Currency 的对象都可以传入 convert 中并返回结果。

但是加拿大元的逻辑与 CanadaDollar 类耦合在一起。如果我添加另一个实现,恰好也是 CAD,那么我无法告诉 PrivateBank 以相同的方式处理我的新实现。 - andreoss
如果CanadaDollarCurrency的实现,则不违反LSP,但是您需要使用任何新货币或汇率更改更新PrivateBank。更好的解决方案是将extra_rate抽象成Currency,以便每种货币都负责其相应的汇率。 - Daly

1
不。 里氏替换原则是关于子类型忠实地展示其超类型的所有属性。它绝不禁止其他代码以不同的方式处理相同类型的不同子类型。
你的示例代码有点臭,但并非因为与LSP冲突。

0
以上被称为“LSP潜在违规”。任何实例检查以识别超类型的子类型都被视为潜在违规。
实现不应因不同的子类型而有所不同。在您的情况下,除了不同的值之外,没有冲突。但仍然可以通过使用函数或值返回汇率而不是检查子类型并设置它来解决这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接