我正在搜索一个带有函数func和参数arg的方法的正确签名,将它们通过网络复制到远程计算机并返回结果.目前签名如下:
def invokeRemote[A,B](address: String, func: A => B, arg: A): B
Run Code Online (Sandbox Code Playgroud)
这样做的问题是,如果参数不是Serializable或Java的原始类型之一,则该方法抛出NotSerializable Exception.
我想出了以下解决方案,以便在编译时捕获此错误...
type Func = (A => B) with Serializable
def invokeRemote[A <: Serializable, B <: Serializable](address: String, func: Func, arg: A): B
Run Code Online (Sandbox Code Playgroud)
...但现在不可能再传递AnyVal类型的参数,如Int,Float或Double,它们没有显式实现Serializable.
方法签名应该如何看起来只接受Serializable对象或AnyVal类型的对象作为参数?
您可以使用隐式自定义特征的上下文绑定,AnyVal并Serializable为该特征提供隐式转换.
trait Ser[M]
implicit def toSer1[T <: AnyVal]: Ser[T] = new Ser[T] {}
implicit def toSer2[T <: java.io.Serializable]: Ser[T] = new Ser[T] {}
def f[T: Ser](a:T): T = a
f(1)
// res2: Int = 1
f("123")
// res3: java.lang.String = 123
f(new Object)
// could not find implicit value for evidence parameter of type Ser[java.lang.Object]
Run Code Online (Sandbox Code Playgroud)
编译器会基于类型的隐含参数,因为有些是提供T <: AnyVal和T <: java.io.Serializable它在这种情况下进行编译.
您可以将隐式定义粘贴在随播对象中,Ser以便在需要时可用.
然后,您的签名变为:
def invokeRemote[A:Ser, B:Ser](address: String, func: A => B, arg: A): B
Run Code Online (Sandbox Code Playgroud)