我正在使用Scala implicits为Java接口定义一个丰富的包装器:
class RichThing { def richStuff: Unit = {} }
Run Code Online (Sandbox Code Playgroud)
在伴侣对象中,我定义了隐式转换和apply工厂方法:
object RichThing {
implicit def rich( thing: JavaThing ) = new RichThing()
def apply() = new RichThing()
}
Run Code Online (Sandbox Code Playgroud)
有了这个,我可以实例化接口的Java实现并像使用它一样RichThing(由于隐式转换):
new JavaThingImpl().richStuff
Run Code Online (Sandbox Code Playgroud)
我也可以RichThing使用工厂方法创建一个(由于apply方法):
val a = RichThing()
Run Code Online (Sandbox Code Playgroud)
我想做的是以相同的方式实例化接口的任意Java实现.这不起作用,因为Scala然后查找实现的伴随对象,但找不到:
val b = JavaThingImpl() // "not found: value JavaThingImpl"
Run Code Online (Sandbox Code Playgroud)
我可以为Java实现创建一个Scala伴侣对象:
object JavaThingImpl { def apply() = new RichThing() }
Run Code Online (Sandbox Code Playgroud)
但关键是要使这个工作适用于任何(特别是未知的)接口实现.
有没有办法实现这个?例如,基于RichThing对象中的隐式转换,动态地为Java实现创建Scala伴随对象?
或者从Java端创建Scala伴侣对象,也许在抽象类中?
拿这个代码:
class Register(var value:Int = 0) {
def getZeroFlag() : Boolean = (value & 0x80) != 0
}
object Register {
implicit def reg2int(r:Register):Int = r.value
implicit def bool2int(b:Boolean):Int = if (b) 1 else 0
}
Run Code Online (Sandbox Code Playgroud)
我想这样使用它:
val x = register.getZeroFlag + 10
Run Code Online (Sandbox Code Playgroud)
但我受到了欢迎:
type mismatch; found : Boolean required: Int
Run Code Online (Sandbox Code Playgroud)
怎么了?我是否需要定义一个隐式的函数返回一个bool?
我正在尝试创建一个类型类Default,它提供给定类型的默认值.这是我到目前为止提出的:
trait Default[A] {
def value: A
}
object Default {
def withValue[A](a: A) = new Default[A] {
def value = a
}
def default[A : Default]: A = implicitly[Default[A]].value
implicit val forBoolean = withValue(false)
implicit def forNumeric[A : Numeric] =
withValue(implicitly[Numeric[A]].zero)
implicit val forChar = withValue(' ')
implicit val forString = withValue("")
implicit def forOption[A] = withValue(None : Option[A])
implicit def forAnyRef[A >: Null] = withValue(null : A)
}
case class Person(name: String, age: Int)
case class …Run Code Online (Sandbox Code Playgroud) 昨天我有一个奇怪的错误,我最终缩减为以下代码:
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29).
Type in expressions to have them evaluated.
Type :help for more information.
scala> class X extends Function[String, Int] { def apply(x: String) = Integer.parseInt(x) }
defined class X
scala> implicit val x = new X
x: X = <function1>
scala> "56" / 2
res2: Int = 28
Run Code Online (Sandbox Code Playgroud)
我希望这会引发异常,因为String没有/方法.相反,Scala将隐式变量视为隐式方法(因为它实现Function[String,Int])并将字符串"56"转换为整数56.
这是如何运作的?基于隐式搜索的规则,我不认为将充当函数的隐式变量.
我写使用C#游戏,发现许多情况下,其中一个功能需要一个委托,我在一个函数名,而不是创建和缓存的委托作为参数,而不是用在不经意间过去了.这会导致为每个对这些函数的调用创建一个委托对象,然后在函数返回时立即变为垃圾.
我想找到我犯了这个错误的所有地方,我宁愿避免阅读每个文件的每一行寻找它们(有多年的代码值).我看到VB有一个'选项严格'会禁用隐式构造的对象,如果C#有这个功能,我觉得这对我有用,但我认为不行.我还审查了编译器警告选项,它们似乎都没有帮助.
是否有任何合理方便的方法来识别由隐式委托推理创建的这些对象,以便我可以找到我需要创建/缓存回调以避免垃圾的位置?
我对Joshua Suareth的书Scala中的"5.1.3隐式解决方案"中的描述感到困惑,第100页:
Scala对象不能包含implicits的伴随对象.因此,必须从外部作用域提供与该对象类型的隐式作用域所需的对象类型相关的隐含.这是一个例子:
scala> object Foo {
| object Bar { override def toString = "Bar" }
| implicit def b : Bar.type = Bar
|}
defined module Foo
scala> implicitly[Foo.Bar.type]
res1: Foo.Bar.type = Bar
Run Code Online (Sandbox Code Playgroud)
但是我在REPL中隐藏了对象Bar:
scala> object Foo {
| implicit object Bar {
| override def toString = "isBar" }
| }
defined module Foo
scala> implicitly[Foo.Bar.type]
res0: Foo.Bar.type = isBar
Run Code Online (Sandbox Code Playgroud)
似乎它不需要在外部范围中定义隐式.或者我认为约书亚的意思完全错了?
Scala中的类型类模式涉及定义特征,例如:
trait Show[T] {
def show(obj: T): String
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以定义此类型类的实例化:
object Show {
implicit val string = new Show[String] {
def show(obj: String): String = obj
}
implicit object BooleanShow extends Show[Boolean] {
def show(obj: Boolean): String = obj.toString
}
}
Run Code Online (Sandbox Code Playgroud)
为伴随对象中的基本类型定义这些实例化的优点是,无论何时涉及类型类(粗略地),它们都自动在范围内.
在功能上它似乎将实例化定义为隐式val或隐式对象不会发生太大变化.
有区别吗?有一种方式比另一种更好吗?
[error] test.scala:31: ambiguous implicit values:
[error] both method taggedQueryParamDecoder in trait ExternalInstances0 of type [A, T](implicit evidence$2: org.http4s.QueryParamDecoder[A])org.http4s.QueryParamDecoder[scalaz.@@[A,T]]
[error] and method iiQueryParamDecoder in trait ExternalInstances1 of type [B](implicit ii: foo.InvariantInstances[B])org.http4s.QueryParamDecoder[B]
[error] match expected type org.http4s.QueryParamDecoder[scalaz.@@[String,foo.tags.Social]]
[error] implicitly[QueryParamDecoder[String @@ Social]]
[error] ^
Run Code Online (Sandbox Code Playgroud)
我导入instances._; instances延伸ExternalInstances1和ExternalInstances1延伸ExternalInstances0.由于这种继承,我希望其ExternalInstances1成员能够赢得胜利ExternalInstances0,而不是产生歧义.
为什么会发生这种情况,我该如何解决?谢谢.
来源位于http://scastie.org/12233,转载如下:
/***
scalaVersion := "2.11.7"
libraryDependencies += "org.http4s" %% "http4s-core" % "0.10.0"
resolvers ++= Seq(
"tpolecat" at "http://dl.bintray.com/tpolecat/maven",
"Scalaz Bintray Repo" …Run Code Online (Sandbox Code Playgroud) 问题是基于这里的讨论.这是设置:
implicit def CToC2(obj: C1): C2 = {
new C2()
}
class C1() {
def f[U](f: (Int, Int) => U): U = f(1, 1)
}
class C2() {
def f[U](f: ((Int, Int)) => U): U = f(2, 2)
}
Run Code Online (Sandbox Code Playgroud)
我希望尝试C2使用存在的签名来调用函数,scala会使用隐式转换来满足调用:
val c1 = new C1()
val ff: ((Int, Int)) => Unit = t => println(t._1 + t._2)
Run Code Online (Sandbox Code Playgroud)
但这失败了:
scala> c1.f(ff)
Error:(16, 7) type mismatch;
found : ((Int, Int)) => Unit
required: (Int, Int) => ?
Run Code Online (Sandbox Code Playgroud)
有趣的是,如果我删除类型参数 …