【问题标题】:Scala Extending Parameterized Abstract ClassScala扩展参数化抽象类
【发布时间】:2012-09-05 21:06:40
【问题描述】:

我对 Scala 相当陌生,正在编写一个 API 库并尝试仅使用 val 和不可变对象(在可能的情况下)。我正在尝试确定建模对象的正确方法。假设有几个“Post”对象,它们都共享一些公共字段,并且每个都添加自己的特定字段:

abstract class Post(val id: Int, val name: String, ...)
case class TextPost(val id: Int, val name: String, ..., val text: String) extends Post(id, name, ...)
case class PhotoPost(val id: Int, val name: String, ..., val url: String) extends Post(id, name, ...)

这种方法增加了很多重复的声明和样板代码,尤其是在处理许多 Post 子类和在抽象类中声明的共享字段时。在我看来,这是由于使用只能由构造函数初始化的 vals 引起的。是否有更好的方法来创建此处详述的关系,或者我必须因为只想使用不可变对象而遭受这种痛苦?

【问题讨论】:

    标签: oop scala inheritance


    【解决方案1】:

    首先,case-class 构造函数中的val 修饰符是多余的,Scala 编译器已经“免费”将它们提供给您(这是 case-classes 的特性之一)。如果你真的尝试编译它,你会看到由于未声明的覆盖而发生错误:

    abstract class Post(val id: Int, val name: String )
    case class TextPost(id: Int, name: String) extends Post(id, name )
    case class PhotoPost(id: Int, name: String) extends Post(id, name )
    
    <console>:10: error: overriding value id in class Post of type Int;
     value id needs `override' modifier
               case class PhotoPost(id: Int, name: String) extends Post(id, name )
                                    ^
    

    我个人建议尽可能少地使用带有构造函数参数的抽象类。 Scala 的特性在这里做得更好。您(抽象地)声明字段,而不是构造函数参数;然后案例类开始了,由于他们自动提出他们的论点vals,你就完成了:

    trait Post { def id: Int; def name: String }
    case class TextPost(id: Int, name: String, text: String) extends Post
    case class PhotoPost(id: Int, name: String, url: String) extends Post
    

    此外,如果将sealed 添加到trait Post,则可以安全地在模式匹配中使用Post 的子类型,而不会意外丢失大小写。

    【讨论】:

    • 感谢您的回答!就样板代码而言,这种方法基本上可以避免我将派生类中的每个参数声明为 val,但我仍然必须在每个声明中重复所有参数,对吧?我要强调这一点,因为我有 8 个子类和 15 个共享字段,这似乎是一个巨大的 DRY 案例。但是我从您的回答中了解到,没有办法解决这个问题,对吧?
    • 唯一的其他选择是实现通用接口(@98​​7654328@)。这意味着您需要 compose 类型来包含它,但我不知道这是否是您想要的:case class Post(id: Int, name: String); case class TextPost(post: Post, text: String).
    • 我觉得这个答案还不够,因为它没有回答样板问题......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-24
    • 1970-01-01
    • 1970-01-01
    • 2017-01-30
    • 1970-01-01
    • 2016-11-10
    • 1970-01-01
    相关资源
    最近更新 更多