MyClass和MyClass.this.type有什么区别,以及如何将一个转换为另一个?

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中

And*_*kin 5

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,尽管ab均为类型A.

  • @DjuraMarinkov在上面的代码片段中,它是必需的,因为否则`MyClass`的每个实例都有自己的`Param`类型,它与任何其他`MyClass`参数不兼容.因此,除非你想让`MyClass`成为单身,否则制作`Param`内部类是没有任何意义的.如果你决定把它变成一个单身,那么一开始就不太清楚`Abst`特性是什么有益的.目前尚不清楚如何"改进"它,因为你的原始代码看起来像一个XY问题.也许你可以在动机上添加一两段*为什么*你写了这段代码? (2认同)