【发布时间】:2020-10-21 20:51:01
【问题描述】:
我正在学习 Scala 案例类和设计模式。为此,我在下面创建了一个示例,我认为这是使用 Json 类型数据时相当可能的场景。我知道存在执行此操作的库,但我正在手动学习 Scala 解决问题的方法,因为使用库不会帮助我学习。
我想做的主要设计改进是抽象通用代码。
假设我的代码库由许多案例类组成,其中每个案例类都是可序列化的:
trait Base {
def serialize(): String
}
trait Animal extends Base
trait Mammal extends Animal
trait Reptile extends Animal
case class Lizard(name: String, tail: Boolean) extends Reptile {
def serialize(): String = s"""{name: $name, tail: $tail}"""
}
case class Cat(name: String, age: Int) extends Mammal {
def serialize(): String = s"""{name: $name, age: $age}"""
}
case class Fish(species: String) extends Animal {
def serialize(): String = s"""{species: $species}"""
}
case class Pets(group_name: String, cat: Option[Cat] = None, lizard: Option[Lizard] = None, fish: Fish) extends Base {
def serialize(): String = {
// cat and lizard serialize in a similar fashion
val cat_object = cat match {
case Some(c) => s"""cats: ${c.serialize()}"""
case _ => ""
}
val lizard_object = lizard match {
case Some(d) => s"""lizards: ${d.serialize()}"""
case _ => ""
}
// fish serializes in a different way as it is not an option
val fish_object = s"""fish: ${fish.serialize()}"""
s"""{$lizard_object, $cat_object, $fish_object}"""
}
}
val bob = Cat("Bob", 42)
val jill = Lizard("Jill", true)
val pets = Pets("my group", Some(bob), Some(jill), Fish("goldfish")).serialize()
println(pets)
}
现在这里有一个重复的模式:
-
在 Pets 中,当我进行序列化时,我基本上会遍历参数列表中的每个 (key, value) 对(group_name 除外)并执行以下操作:
键:value.serialize()
现在我不知道值的形式,它可以是示例中的选项。此外,假设我有很多像宠物这样的课程。在那种情况下,我必须在需要的每个参数上手动编写许多模式匹配,区分 String、Int、Option[String] 等。有没有办法抽象出这个可序列化的操作,这样如果我有很多案例类像 Pets 一样,我可以简单地运行一个函数并获得正确的结果。
我在这里问了一个有关从案例类中获取声明字段的相关问题,但似乎这种方式不安全,如果我添加更多自定义案例类,以后可能会产生问题:
https://stackoverflow.com/questions/62662417/how-to-get-case-class-parameter-key-value-pairs
【问题讨论】:
-
这不是学习 Scala 的好起点,因为您将源代码符号名称放入数据值中。这涉及使用 reflection ,这在 Scala(或实际上任何语言)中很尴尬。虽然在处理 JSON 时会使用它,但正如您所说,现有的库可以完成这项工作。
-
你想要在这里做的涉及运行时或编译时反射。虽然这些本身都不是超级难,但在没有扎实掌握其他语言的情况下学习它是一种受虐狂。
-
谢谢 我将推迟我对运行时/编译时反射的学习。我以前没有遇到过这个概念。
-
TL;DR;这类问题的答案是typelcass。
-
见What JSON library to use in Scala?。我知道您的问题说您不想使用它,但我仍然推荐它
标签: json scala pattern-matching abstraction case-class