Scala 中的 Nullable 支持
Nullablle support in Scala
我可以在 Scala 对象中使用 Nullable 参数吗?
类似于C#中的Nullable和语法糖:
public int? Age {get; set;}
public string Name {get; set;}
public bool? isAdmin {get; set;}
我可以创建 scala class 对象可以设置其中一些属性而其他属性不能设置吗?
我打算为不同的目的使用多个构造函数。我想确保空值表示未设置该字段。
更新
例如我有以下情况class
case class Employee(age: Int, salary: Int, scaleNum : Int,
name: String, memberId: Int )
我正在使用 GSON 序列化 JSON 中的 class。
然而,在某些情况下,我不想传递某些参数的值,这样 GSON 序列化程序将只包含具有非 NULL 值的参数。
如何使用选项或其他方式实现?
对于您的示例,Scala 中的一个常见声明是:
case class Employee(
age: Option[Int], // For int? Age
name: String // For string Name
// your other decls ...
)
那你就可以轻松使用类型了:
val john = Employee( age = Some(10), name = "John" )
虽然 Scala 2 允许引用类型(如 String 等)的空值,但它从 Scala 3 开始慢慢改变 (https://dotty.epfl.ch/docs/reference/other-new-features/explicit-nulls.html)。
JSON支持
Java 库(如 GSON)对 Scala 一无所知,因此您应该考虑使用其他库来获得支持 Scala 的 JSON 支持:
- 圈子
- 播放json
- jsoniter-scala
- uPickle
- 等等
这些库不仅知道 class 定义中的 Option[]
,而且改进了对 Scala 集合、隐式、默认值和其他 Scala 语言功能的支持。
为此选择一个合适的库非常重要,因为使用 Java JSON 库你最终会得到 Java 风格的 classes 和代码,与其他 Scala 库的兼容性问题。
对于 Circe,您的示例将是:
import io.circe._
import io.circe.syntax._
import io.circe.parser._
import io.circe.generic.auto._
val john = Employee( age = Some(10), name = "John" )
val johnAsJson = john.asJson.dropNullValues
decode[Employee]( johnAsJson ) match {
case Right(johnBack) => ??? // johnBack now is the same as john
case Left(err) => ??? // handle JSON parse exceptions
}
空合并运算符
现在您可能正在寻找 Scala 中的空合并运算符(C# 中的??
,Kotlin 中的?
,...)在哪里。
直接答案 - 语言本身有 none。在 Scala 中,我们以 FP 方式使用 Option(以及其他单子结构或 ADT)。
这意味着,例如:
case class Address(zip : Option[String])
case class Employee(
address: Option[Address]
)
val john = Employee( address = Some( Address( zip = Some("1111A") )) )
你应该避免这种风格:
if (john.address.isDefined) {
if(john.address.zip.isDefined) {
...
}
}
您可以使用 map
/flatMap
s 代替:
john.address.flatMap { address =>
address.zip.map { zip =>
// your zip and address value
??
}
}
// or if you need only zip in a short form:
john.address.flatMap(_.zip).map { zip =>
// your zip value
??
}
或 for-comprehension
语法(基于相同的 flatMaps):
for {
address <- john.address
zip <- address.zip
}
yield {
// doing something with zip and address
??
}
重要的部分是在 Scala 中解决这个问题的惯用方法主要基于 FP 的模式。
我可以在 Scala 对象中使用 Nullable 参数吗?
类似于C#中的Nullable和语法糖:
public int? Age {get; set;}
public string Name {get; set;}
public bool? isAdmin {get; set;}
我可以创建 scala class 对象可以设置其中一些属性而其他属性不能设置吗?
我打算为不同的目的使用多个构造函数。我想确保空值表示未设置该字段。
更新
例如我有以下情况class
case class Employee(age: Int, salary: Int, scaleNum : Int,
name: String, memberId: Int )
我正在使用 GSON 序列化 JSON 中的 class。
然而,在某些情况下,我不想传递某些参数的值,这样 GSON 序列化程序将只包含具有非 NULL 值的参数。
如何使用选项或其他方式实现?
对于您的示例,Scala 中的一个常见声明是:
case class Employee(
age: Option[Int], // For int? Age
name: String // For string Name
// your other decls ...
)
那你就可以轻松使用类型了:
val john = Employee( age = Some(10), name = "John" )
虽然 Scala 2 允许引用类型(如 String 等)的空值,但它从 Scala 3 开始慢慢改变 (https://dotty.epfl.ch/docs/reference/other-new-features/explicit-nulls.html)。
JSON支持
Java 库(如 GSON)对 Scala 一无所知,因此您应该考虑使用其他库来获得支持 Scala 的 JSON 支持:
- 圈子
- 播放json
- jsoniter-scala
- uPickle
- 等等
这些库不仅知道 class 定义中的 Option[]
,而且改进了对 Scala 集合、隐式、默认值和其他 Scala 语言功能的支持。
为此选择一个合适的库非常重要,因为使用 Java JSON 库你最终会得到 Java 风格的 classes 和代码,与其他 Scala 库的兼容性问题。
对于 Circe,您的示例将是:
import io.circe._
import io.circe.syntax._
import io.circe.parser._
import io.circe.generic.auto._
val john = Employee( age = Some(10), name = "John" )
val johnAsJson = john.asJson.dropNullValues
decode[Employee]( johnAsJson ) match {
case Right(johnBack) => ??? // johnBack now is the same as john
case Left(err) => ??? // handle JSON parse exceptions
}
空合并运算符
现在您可能正在寻找 Scala 中的空合并运算符(C# 中的??
,Kotlin 中的?
,...)在哪里。
直接答案 - 语言本身有 none。在 Scala 中,我们以 FP 方式使用 Option(以及其他单子结构或 ADT)。
这意味着,例如:
case class Address(zip : Option[String])
case class Employee(
address: Option[Address]
)
val john = Employee( address = Some( Address( zip = Some("1111A") )) )
你应该避免这种风格:
if (john.address.isDefined) {
if(john.address.zip.isDefined) {
...
}
}
您可以使用 map
/flatMap
s 代替:
john.address.flatMap { address =>
address.zip.map { zip =>
// your zip and address value
??
}
}
// or if you need only zip in a short form:
john.address.flatMap(_.zip).map { zip =>
// your zip value
??
}
或 for-comprehension
语法(基于相同的 flatMaps):
for {
address <- john.address
zip <- address.zip
}
yield {
// doing something with zip and address
??
}
重要的部分是在 Scala 中解决这个问题的惯用方法主要基于 FP 的模式。