【问题标题】:Avoiding the Liskov substitution principle in Scala sub-classes and polymorphism in Seqs避免 Scala 子类中的 Liskov 替换原则和 Seqs 中的多态性
【发布时间】:2014-03-17 14:14:32
【问题描述】:

我有两种促销方式:一种是标准促销,例如“买一送一”,另一种是针对即将到期的产品的短期促销。

这两种类型在这里有些简化,但显示了字段:

case class ShortDatedPromo extends Promotion (val name, val startDate, val endDate, val wasPrice, val nowPrice, val productID)

case class RegularPromo extends Promotion (val name, val description, val terms, val productID, val date)

如您所见,对我们人类来说,这些都只是促销活动。但是,对于 scala 编译器来说,它们是完全不同的野兽。

我从一个基类 Promotion 扩展,以便我可以将它们存储在 Seq[Promotion] 中。也许有 3 个 RegularPromos 和 1 个 ShortDatedPromo。我们的想法是在首页(这是一个 Play 网站)上有一个简单的“促销”部分。

据我了解,如果我在超类中定义所有 getter/setter,我将打破 Liskov 替换原则,因为不能将 RegularPromo 替换为 ShortDated Promo。

然后如何在遍历 Seq[Promotion] 时实现多态分派,而不必有一些类型检查代码?我在这里想念的 Scala 中有什么技巧吗?谢谢

【问题讨论】:

  • 为什么不使用您需要的一些通用方法将Promotion 抽象(或特征)并在具体类中实现它(如ShortDatedPromo 或RegularPromo)?
  • 当然,但 ShortDated 需要“获取 productShelfExpireDate”,但 Regular 不需要。因此,迭代 Seq 的代码将尝试调用 RegularPromo 上的函数并失败......

标签: scala playframework-2.0


【解决方案1】:

在基本特征中定义公共 val 是非常好的。因此,如果您要以完全相同的方式展示您的促销活动,只使用那些常见的 val,这是一个可以接受的解决方案。

如果存在差异,我会将 2 个 Seq(每种促销类型一个)传递给模板。

您还可以使用模式匹配来查找具体类型(在这种情况下,Promotion 可能应该被密封)。

最后一个解决方案是使用 HList 和 shapeless 中的多态函数,这很有趣,但考虑到您的用例,显然有点矫枉过正。

干杯

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-12
    • 2014-06-05
    • 2010-12-03
    • 2019-10-29
    • 1970-01-01
    相关资源
    最近更新 更多