Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何将类型映射到Scala中的值?_Java_Scala_Types - Fatal编程技术网

Java 如何将类型映射到Scala中的值?

Java 如何将类型映射到Scala中的值?,java,scala,types,Java,Scala,Types,我认为在ScalaMap[Class[\up>中,您真正想要的是从Rank到Int的部分函数。与为域的所有元素定义的全部函数不同,部分函数只能为其中的一些元素定义 另外,如果您不介意另一个建议的话,抛出异常并不符合函数式编程的精神。我不会将函数式方法强加给您,因为Scala完全可以用于面向对象(类似Java)中方式。但我要建议它。它说-不要扔!我总是说扔就像完全撕裂了你程序的结构。它撕开墙壁,说“好吧,现在我走捷径”。这几乎就像goto语句。如果你决定使用异常,我敢肯定你可以修改我的示例来合并它

我认为在Scala
Map[Class[\up>中,您真正想要的是从
Rank
Int
的部分函数。与为域的所有元素定义的全部函数不同,部分函数只能为其中的一些元素定义

另外,如果您不介意另一个建议的话,抛出异常并不符合函数式编程的精神。我不会将函数式方法强加给您,因为Scala完全可以用于面向对象(类似Java)中方式。但我要建议它。它说-不要扔!我总是说扔就像完全撕裂了你程序的结构。它撕开墙壁,说“好吧,现在我走捷径”。这几乎就像goto语句。如果你决定使用异常,我敢肯定你可以修改我的示例来合并它们

我的建议是,不要抛出,而是明确指出您的函数最终可能会导致错误值。您可以使用
或者[MyErrorType,MyValueType]
轻松地执行此操作。这样,您最终返回的值需要是
左(instanceOfMyErrorType)
或者
右(instanceOfMyValueType)
。之后,在一些需要处理错误的代码中,您可以随时检查您手中是否有
,并相应地采取行动(例如,如果左记录错误并返回400 HTTP响应或其他响应)

代码如下:

sealed trait Rank
case object Ace extends Rank
case object King extends Rank
case object Queen extends Rank
case object Jack extends Rank
case object Ten extends Rank
// ...

final case class Error(msg: String)

val exampleMapping: PartialFunction[Rank, Int] = 
  (rank: Rank) => rank match {
    case Ace => 11 
    case King => 10
    case Queen => 10
    case Jack => 10
    // No Ten!
  }

def valuations(rank: Rank, f: PartialFunction[Rank, Int]): Either[Error, Int] =
  f.andThen(rank => Right(rank)).applyOrElse(
    rank,
    (v: Rank) => Left(Error(s"No such element: $v"))
  )

val a = valuations(King, exampleMapping) // Right(10)
val b = valuations(Ten, exampleMapping)  // Left(Error(No such element: Ten))
上面代码中最有趣的部分是
估价方法

  • 给我一个
    rank:rank
    和一个从
    rank
    Int
    的部分函数,我将返回
    Int
    错误
  • 我现在要做的是,我用一个函数组合提供的函数,该函数将该值转换为
    右(该整数)
    (或者,用数学术语,将后者与前者组合;
    f,然后g
    表示
    g(f(x))
    ,而
    f组合g
    表示
    f(x))
    …我总是觉得使用
    在精神上更容易,然后
  • 将上面定义的组合应用于
    rank
    参数,如果该函数没有为
    rank
    定义结果,那么返回
    Left(error)
当然,您可以有许多不同的部分函数,其他用户可以定义自己的函数,等等。不过请注意两件事:

  • 使用sealed trait意味着没有人可以扩展
    Rank
    。这对我来说是有意义的。但是,如果您希望以后不仅能够添加不同的映射,甚至能够添加新的
    Rank
    s,那么就不要将trait密封起来
  • 创建您的case类是因为它们不应该被扩展,通过将它们设置为最终类,若您试图定义一个总函数(而不是部分函数),编译器将向您发出警告,但由于意外地忽略了某个等级的
    案例
    ,因此忘记了处理某些案例。对于案例对象,如果您也将它们标记为final也可以,但这不是强制性的,因为它们无论如何都不能扩展(它们只能有一个实例,就像Java中的singleton)
如果出于任何原因,您后来决定在映射未定义时不希望返回错误,而是希望使用一个默认映射,该映射具有所有列组的所有默认值(=它不是一个局部函数
Rank=>Int
,而是一个总函数),那么这也很容易做到。尝试一下吧


最后请注意,Scala 3将有非常好的枚举,这是您在Java中熟悉的,而Scala 2缺少的。

我认为@slouc answer很好(代数数据类型(ADT)/密封特征、错误值等),但您确实应该避免使用分部函数(除了某些方法,如
List#collect
,它在未定义的输入上不会失败)并尽可能多地使用total函数。您可以将
exampleMapping
转换为
Rank=>选项[Int]
,但我认为您应该改用map

密封特征等级
对象秩{
//如果你想把这些放在窝里就看你了
case对象扩展秩
case-object-King扩展了等级
case对象扩展秩
case对象Jack扩展秩
案例对象10扩展等级
案例对象九扩展了等级
//...
}
val exampleMapping=Map(
排名.Ace->11,
等级:国王->10,
等级:女王->10,
排名:杰克->10,
排名10->10
)
def赋值(秩:秩,m:Map[rank,Int]):要么[Error,Int]=
m、 get(rank).toRight(新错误“无此类元素:$rank”))
如果您实际上不需要变量映射(或者如果映射在编译时已知,那么最好将它们实现为单独的列组类型),那么您应该只在中实现值(这不是更像枚举吗?)

密封抽象类秩(val-maybeValue:Option[Int])
对象秩{
案例对象Ace扩展等级(部分(11))
case object King扩展秩(一些(10))
case object Queen扩展秩(一些(10))
案例对象杰克扩展等级(一些(10))
案例对象十扩展等级(一些(10))
案例对象九扩展秩(无)
//...
}
def赋值(秩:秩):要么[Error,Int]=
rank.maybeValue.toRight(新错误“无此类元素:$rank”))
如果值不是可选的(如Java枚举…):

密封抽象类秩(val值:Int)
对象秩{
案例对象Ace扩展秩(11)
案例对象国王扩展等级(10)
案例对象扩展秩(10)
案例对象杰克扩展等级(10)
案例对象10扩展秩(10)
案例对象九扩展秩(9)
//...
}
//如果错误不是可选的,我们甚至不需要错误,而且这个方法现在有点毫无意义。。。
def估值(秩:秩):Int=rank.value
现在,对于多个等级类型,您可以使用子类型进行泛化(这会破坏您的ADT)(等等,我们甚至可以将Java子类化吗
class Valuations(val map: Map[Class[_ <: Rank], Int]) {

  def valueOf(rank: Rank): Int = {
    val key = rank.getClass
    if (map.contains(key) map.get(key) else {
      throw new NoSuchElementException("No match for " + rank.toString)
    }
  }

}
sealed trait Rank
case object Ace extends Rank
case object King extends Rank
case object Queen extends Rank
case object Jack extends Rank
case object Ten extends Rank
// ...

final case class Error(msg: String)

val exampleMapping: PartialFunction[Rank, Int] = 
  (rank: Rank) => rank match {
    case Ace => 11 
    case King => 10
    case Queen => 10
    case Jack => 10
    // No Ten!
  }

def valuations(rank: Rank, f: PartialFunction[Rank, Int]): Either[Error, Int] =
  f.andThen(rank => Right(rank)).applyOrElse(
    rank,
    (v: Rank) => Left(Error(s"No such element: $v"))
  )

val a = valuations(King, exampleMapping) // Right(10)
val b = valuations(Ten, exampleMapping)  // Left(Error(No such element: Ten))