Dju*_*kov 1 inheritance types scala
我有类似这样的情况:
trait Abst{
type T
def met1(p: T) = p.toString
def met2(p: T, f: Double=>this.type){
val v = f(1.0)
v.met1(p)
}
}
class MyClass(x: Double) extends Abst{
case class Param(a:Int)
type T = Param
val s = met2(Param(1), (d: Double) => new MyClass(d))
}
Run Code Online (Sandbox Code Playgroud)
并且在我运行之前它不显示错误,然后它说:
类型不匹配; 发现:MyClass,必需:MyClass.this.type
我尝试了一个泛型类型的解决方案,但后来我发现这个与TT不同的冲突
所以我只需要克服上面的错误信息,如果可能的话?
更新
因此,事实证明这this.type是该单个实例的单例类型.我在评论中提出了用法
val s = met2(Param(1), (d: Double) => (new MyClass(d)).asInstanceOf[this.type])
Run Code Online (Sandbox Code Playgroud)
所以,如果有人对此发表评论,我知道它是多么丑陋,只是感兴趣它是多么不安全?
你们都建议在课外移动Param的定义,我绝对同意.所以它的定义将在伴随对象MyClass中
的this.type是单类型由一个单值居住,即this.因此,接受类型函数f: X => this.type作为参数保证是无意义的,因为每次调用都f可以被替换为this(加上执行的副作用f).
这是一种强制代码编译的方法,只需进行最少的更改:
trait Abst { self =>
type T
def met1(p: T) = p.toString
def met2(p: T, f: Double => Abst { type T = self.T }){
val v = f(1.0)
v.met1(p)
}
}
case class Param(a:Int)
class MyClass(x: Double) extends Abst {
type T = Param
val s = met2(Param(1), (d: Double) => new MyClass(d))
}
Run Code Online (Sandbox Code Playgroud)
但老实说:不要这样做.并且也不做任何F-bounded-stuff,它可能最终会变成一团糟,特别是如果你不熟悉这种模式.相反,重构您的代码,以便您没有任何自引用螺旋.
更新
备注为什么告诉编译器其他(new MyClass(d))类型的类型是一个非常糟糕的主意:this.typethis: MyClass
abstract class A {
type T
val x: T
val f: T => Unit
def blowup(a: A): Unit = a.asInstanceOf[this.type].f(x)
}
object A {
def apply[X](point: X, function: X => Unit): A = new A {
type T = X
val x = point
val f = function
}
}
val a = A("hello", (s: String) => println(s.size))
val b = A(42, (n: Int) => println(n + 58))
b.blowup(a)
Run Code Online (Sandbox Code Playgroud)
这炸毁了ClassCastException,尽管a和b均为类型A.
| 归档时间: |
|
| 查看次数: |
69 次 |
| 最近记录: |