object test {
trait Test {
def apply() = {
println("calling apply in trait test")
this
}
}
object Test {
def apply(f: Int => String): Test = {
println("calling apply in object Test")
new Test {
println("test123")
def apply(a: Int) = f(a) // this apply function should be available when call Test(f)?
}
}
}
def fun(a:Int)=a.toString
val f=fun _
val a=Test(f)
a()
a(1) // why this failed? a is created by calling Test(f) which is actually
//calling apply function of object Test, and that function return a Test
//with an addition function of apply(a:Int). And a(1) is actually calling
//apply(1), but why it doesn't compile?
}
答案 0 :(得分:4)
您的签名:
def apply(f: Int => String): Test = { … }
将结果限制为Test
特征,但不包括新的apply
。通过省略结果类型,返回的对象将是Test+apply
,它将按照您的预期执行:
def apply(f: Int => String) = { … }
答案 1 :(得分:2)
此失败的原因是您的类型Test
是使用apply
方法定义的,该方法采用空参数列表。使用new Test { ... }
,您可以创建Test
的匿名子类。虽然您使用另一个带有apply
参数的版本重载Int
,但对象的apply
方法的返回类型仅为Test
。因此,从外部来看,这种重载方法是不可见的。
说明您的问题:
trait Foo
def mkFoo(): Foo = new Foo { def bar = 1234 }
val f = mkFoo()
f.bar // we don't know anything about bar
只需定义特征Test
即可包含其他apply
方法:
trait Test {
def apply() = {
println("calling apply in trait test")
this
}
def apply(i: Int): String // abstract
}
编辑:作为完整性问题,如果您使用@samuel tardieu答案中所示的“精炼”返回类型,从技术上讲,您使用的是“结构类型”,它带有一点点性能阴谋,因为该方法将使用运行时反射调用。