Scala 使用类型参数def实现trait无法编译
我想我可能用这个做了一些非常愚蠢的事情,但下面的代码片段并没有编译Scala 使用类型参数def实现trait无法编译,scala,Scala,我想我可能用这个做了一些非常愚蠢的事情,但下面的代码片段并没有编译 scala> case class Foo1(i: Int) defined class Foo1 scala> trait Foo1{def testFoo[T](l1 : List[T] ) : List[T] } defined trait Foo1 然后实现如下特征 scala> implicit val foodVal = new Foo1{ | def testFoo[Foo1](
scala> case class Foo1(i: Int)
defined class Foo1
scala> trait Foo1{def testFoo[T](l1 : List[T] ) : List[T] }
defined trait Foo1
然后实现如下特征
scala> implicit val foodVal = new Foo1{
| def testFoo[Foo1](l:List[Foo1] ) = {
| for{
| a <- l
| if (a.i == 1)
| } yield a
| }
| }
<console>:13: error: value i is not a member of type parameter Foo1
在REPL中,定义如下:
trait Foo1{def testFoo[T](l1 : List[T] ) : List[T] }
正在替换类定义
case class Foo1(i: Int)
如果尝试使用“粘贴”命令执行相同的操作,您将看到无法同时定义这两者:
scala> :paste
// Entering paste mode (ctrl-D to finish)
case class Foo1(i: Int)
trait Foo1{def testFoo[T](l1 : List[T] ) : List[T] }
// Exiting paste mode, now interpreting.
<console>:36: error: Foo1 is already defined as case class Foo1
trait Foo1{def testFoo[T](l1 : List[T] ) : List[T] }
^
要回答更新问题,答案是声明和实现之间的差异 当我以下面的形式编写参数化特征的实现时,我说的是“用具体类型
Foo
替换抽象类型T
”
但是,当我重写一个由类型参数化的方法并更改该类型的名称时,我所做的只是为该抽象类型指定一个不同的名称。我不是指定要使用的特定具体类,而是指定一个新符号来标识我正在操作的抽象类型
trait Bar {
def something[T](t: T) : T
}
val instance = new Bar {
def something[Foo](t: Foo) : Foo = { ... }
}
因此,在上面的示例中,Foo
不是一个具体的类型Foo
,而Foo
只是一个符号,表示将根据传递给方法的参数类型具体化的任意类型
因此,即使在同一范围内有一个名为Foo
的具体类型,它也会被引入的类型参数Foo
所遮蔽,并且在该方法的上下文中,对Foo
的任何引用或Foo
的实例都是对抽象类型参数Foo
的引用,不是具体的类型Foo
trait Bar[T] {...}
val instance = new Foo[Bar] { ... }
def testFoo[Foo1](l:List[Foo1])={
行中,Foo1
是一个新的泛型类型参数,而不是您的案例类的类型Foo1
case class Foo1(i: Int)
trait Foo2 {
type T
def testFoo(l1 : List[T] ) : List[T]
}
implicit val foodVal: Foo2 = new Foo2 {
type T = Foo1
def testFoo(l: List[T]) = {
for { a <- l if a.i == 1 } yield a
}
}
通过this访问完成示例。
class Bar[T] {
type Inner = T
def func[Inner](t: Inner) = {
// won't compile because the "Inner" type of the class is initialized with T
val test: this.Inner = t
}
}
如果你不进一步指定类型参数,它可以是
任何(东西)。如果你需要一个带有特定API的类型。你需要告诉编译器,使用你的第一个示例不会像写的那样工作,因为类型t@SaschaKolberg谢谢。我更新了我的问题。你介意在“更新”中解释这个问题吗部分?谢谢。我更新了我的问题。你介意在“更新”中解释问题吗部分?添加了一个更新,希望能够解决您的问题。顺便说一句,一个单独的问题可能会更好,因为未来的读者和搜索答案的人在阅读多个问题和答案的更新时很难弄清楚发生了什么。
case class Foo1(i: Int)
trait Foo2 {
type T
def testFoo(l1 : List[T] ) : List[T]
}
implicit val foodVal: Foo2 = new Foo2 {
type T = Foo1
def testFoo(l: List[T]) = {
for { a <- l if a.i == 1 } yield a
}
}
class Foo(arg: Int) {
val field: Int = 1
def func(field: String) = {
// here field will always refer to the function paramter
// if you want to access the class field you would have to call this.field
}
}
class Bar[T] {
def func[T](t: T) = {
// within the scope of the function T IS NOT "Bar#T".
// However, you cannot access the class type parameter with "this.T" in this example
}
def func2(t: T) = {
// here T is the classes type parameter T
}
}
class Bar[T] {
type Inner = T
def func[Inner](t: Inner) = {
// won't compile because the "Inner" type of the class is initialized with T
val test: this.Inner = t
}
}
trait Api {
def func: String
}
def func[T <: Api](arg: T) = {
arg.func // yay
}