在纯Scala环境中,如果我想将工厂方法"添加"到现有对象,我可以执行以下操作:
object Test
object Extensions {
object RichTest {
def someFactory = new Test()
}
implicit def fromTest(t: Test.type) = RichTest
}
...
import Extensions._
val t = Test.someFactory
Run Code Online (Sandbox Code Playgroud)
我需要将这样的功能与现有的Java类结合使用.在我的具体的例子,我想一个工厂方法添加fromLocation到类com.google.android.maps.GeoPoint(和我想每一个Android开发者就会知道为什么这将是有益的;-)).
但是,如果我尝试做类似的事情
implicit def fromGeoPoint(t: GeoPoint.type) = RichTest
Run Code Online (Sandbox Code Playgroud)
我收到一个错误说明
类型不匹配; 发现:com.google.android.maps.GeoPoint.type(底层类型对象为com.google.android.maps.GeoPoint)必需:AnyRef
所以我想知道是否有任何方式可以实现上述方法 - 或者提供隐式转换Location是否GeoPoint是Scala中的首选方式,因此Location可以在GeoPoint需要时使用?
根据评论中的要求,使用场景:
// Callback you get from the GPS
override def onLocationChanged(l: Location) {
// You want to put a marker on a map, hence a …Run Code Online (Sandbox Code Playgroud) 我可以使用调试隐式的建议:
我想使用隐含的,x:
type T
trait HasT {
implicit def x: T = ...
}
Run Code Online (Sandbox Code Playgroud)
但我还需要从某个包中导入通配符foo.我尝试了两种不同的方式来介绍两者:
class UseT extends HasT {
import foo._
implicitly[T] // fails! "could not find implicit value"
// use foo stuff
}
Run Code Online (Sandbox Code Playgroud)
和
class UseT {
object hasT extends HasT
import hasT.x
import foo._
implicitly[T] // fails! "could not find implicit value"
}
Run Code Online (Sandbox Code Playgroud)
两者都失败了"找不到"(不是"模糊的含义值").
当x: T通过继承或导入在方法调用点访问隐式标识符时会发生这种情况.
我的解决方法是在导入之前将x重新绑定到隐式val.以下两项工作:
implicit val x2: T = implicitly[T]
import foo._
implicitly[T] // works!
Run Code Online (Sandbox Code Playgroud)
和
implicit val …Run Code Online (Sandbox Code Playgroud) 问题是为什么下面的代码不能用于类型推断(下面是一个REPL会话来演示),它可以修复吗?更具体地说,这与编译器用于推断返回类型的CanBuildFrom的使用有何不同?
鉴于此代码:
object S {
import java.net._
trait UrlLike[T] {
def url(s: String): T
}
object UrlLike {
implicit object str extends UrlLike[String]{def url(s: String) = s}
implicit object url extends UrlLike[URL]{def url(s: String) = new URL(s)}
implicit object uri extends UrlLike[URI]{def url(s: String) = new URI(s)}
}
trait UrlSupport {
val _url: String
def url[T : UrlLike]: T = implicitly[UrlLike[T]].url(_url)
}
}
Run Code Online (Sandbox Code Playgroud)
我在REPL(2.8.1)中有这个会话:
scala> :load c:\temp\UrlTest.scala
Loading c:\temp\UrlTest.scala...
defined module S
scala> import java.net._
import java.net._
scala> import S._ …Run Code Online (Sandbox Code Playgroud) 让我们声明一个def和一个等价函数作为val:
scala> def optional(x:Int):Option[String] = None
optional: (x: Int)Option[String]
scala> val optional2:(Int)=>Option[String] = (i:Int) => None
optional2: Int => Option[String] = <function1>
Run Code Online (Sandbox Code Playgroud)
现在为什么这不起作用?
scala> List(1).flatMap(optional2)
<console>:9: error: type mismatch;
found : Int => Option[String]
required: Int => scala.collection.GenTraversableOnce[?]
List(1).flatMap(optional2)
^
Run Code Online (Sandbox Code Playgroud)
虽然这两个都做到了吗?
scala> List(1).flatMap(optional)
res4: List[String] = List()
scala> List(1).flatMap(optional2(_))
res5: List[String] = List()
Run Code Online (Sandbox Code Playgroud)
由于Option不是GenTraversableOnce的子类型,我认为这必须与implicits有关,但我无法弄清楚究竟是什么.我正在使用Scala 2.9.1.
在Scala中,您可以执行以下操作:
def foo(implicit v: Int) = println(v);
def h(x: Int) = { implicit val i: Int = x; foo }
h(42)
> 42
Run Code Online (Sandbox Code Playgroud)
hcall将foo引用作为闭包.
尝试传递foo给h参数并不奇怪:
def g(x: Int)(f: Int => Unit) = { implicit val i: Int = x; f }
Run Code Online (Sandbox Code Playgroud)
但它不会起作用:
g(1)(foo)
> error: could not find implicit value for parameter v: Int
Run Code Online (Sandbox Code Playgroud)
我认为它正在发生的是foo被称为实际参数的评估.是对的吗?
当传递具有普通参数列表的函数(非隐式)时,不会评估该函数:
def foo2(v: Int) = println("Foo2")
g(1)(foo2)
> Int => Unit = <function1>
Run Code Online (Sandbox Code Playgroud)
这是预期结果,并且foo2 …
Mapper Automap:
Mapper.CreateMap<ObjectType1, ObjectType2>()
.ForMember(o1 => o1.PropName, mapper => mapper.MapFrom(o2 => o2.Prop2Name));
Mapper.Map(object1, object2);
Run Code Online (Sandbox Code Playgroud)
隐含运算符:
public static implicit operator Object1(Object2 o2)
{
Object1 o1 = new Object2();
//Mapping code here...
return o1;
}
Run Code Online (Sandbox Code Playgroud) 这个隐式val如何导致StackOverFlowError?
(削减我的原始代码,仍然导致错误)
object Complicit {
// a class with name, default, and conversion function as implicit val
case class CC[A](name: String, defaultValue: A)(implicit val convert: String => A) {
def getFrom(s: String): A= try {
convert(s)
} catch {
case t: Throwable =>
println("ERROR: %s".format(t)) // just to see the StackOverflowException
defaultValue
}
}
// this works fine
object Works {
val cc1= CC("first", 0.1)(_.toDouble)
}
// this causes java.lang.StackOverflowError due to the implicit
object Fails {
// !!! StackOverFlowError …Run Code Online (Sandbox Code Playgroud) 在Scala中,我可以使用上下文边界:
def sort[T : Ordered](t: Seq[T])
Run Code Online (Sandbox Code Playgroud)
意思是:
def sort[T](t: Seq[T])(implicit def Ordered[T])
Run Code Online (Sandbox Code Playgroud)
如果我有一个包含两个通用参数的类怎么办?即我希望能够确保我有一个Writer[T, String].是否有一种语法,我可以使用上下文边界(T : ...)或我需要显式隐式(这是有趣的写).
这是一个简单的重现器,我在其中定义了一个带有隐式重新排序转换的"可交换"对类型.如果函数的参数f位于预先存在的命名值(t在示例中),则编译器会按预期应用隐式转换.但是,如果我尝试f直接调用literal CommutativePair,它会因类型错误而失败.在这种情况下,编译器不应用隐式重新排序转换.
object repro {
import scala.language.implicitConversions
case class CommutativePair[A, B](a: A, b: B)
object CommutativePair {
// Support a kind of commutative behavior via an implicit reordering
implicit def reorderPair[B, A](pair: CommutativePair[B, A]) =
CommutativePair(pair.b, pair.a)
}
// The idea is to allow a call to 'f' with Pair[Int, String] as well,
// via implicit reorder.
def f(p: CommutativePair[String, Int]) = p.toString
val t = CommutativePair(3, "c")
// This works: the implicit …Run Code Online (Sandbox Code Playgroud) 第一个示例成功找到了对方法的隐式转换foo(String),但是只要我添加一个类型参数(请参阅fails参考资料),编译就不再解析它了:
object works {
class A {
def foo(): String = ???
}
implicit class PimpedA(a: A) {
def foo(i: String): String = ???
}
val a = new A()
a.foo("test") //compiles
}
object fails { //same as `works`, but adds type parameter
class A {
def foo[T](): String = ???
}
implicit class PimpedA(a: A) {
def foo[T](i: String): String = ???
}
val a = new A()
PimpedA(a).foo("test") // compiles
a.foo("test") // error: too …Run Code Online (Sandbox Code Playgroud)