使用 Scala 特征来标记类的实例



我有一个表示 3D 向量的案例类,我正在尝试使用特征来标记每个向量,并带有与每个问题域相关的参考系。 更具体地说,我正在尝试做这样的事情:

trait bFrame
type bVector = Vector with bFrame
/** Inertial position of the point represented in b+ */
def p_b:bVector = Vector(x + r * sP, y - cP*sR*r, z - cP*cR*r) with bFrame

构造函数中的表达式计算结果为双倍,在我尝试这个特质技巧之前一切正常。 我读过您可以将特征应用于类的实例,而不仅仅是类本身,但它似乎在这里不起作用。 我得到的错误是"';'预期,但'有'找到'。 我想使用类型系统来检查参考系,而不必修改原始类。 有没有办法做到这一点?

注释中没有足够的空间来回答

它看起来不像是创建一个新的匿名类。当我添加....

它是=(

例:

$ cat T.scala
trait A
case class T(name: String)
object B extends App {
  val a = new T("123") with A
  println(a)
}
$ scalac -Xprint:typer T.scala

我跳过了大部分输出 - 您可以自己检查。最有趣的:

...
private[this] val a: T with A = {
  final class $anon extends T with A {
    def <init>(): <$anon: T with A> = {
      $anon.super.<init>("123");
      ()
    }
  };
  new $anon()
};
<stable> <accessor> def a: T with A = B.this.a;
...

如您所见 - 匿名类初始化。

我想

我想通了。 目前尚不清楚原因,但出于某种原因,Scala(从 2.12.2 开始(不喜欢您使用构建案例类的"应用"方式。 我必须添加"新"才能使其工作。 另外,我最初应该更清楚,Vector 是一个表示数学意义上向量的案例类,而不是 Scala 集合。 我在这里将其更改为Vector3D以使其更清晰。 此外,2.12.2 编译器说打印"b-frame 中的矢量"的行无法访问,但是当我运行它时,该行被执行(即输出是您所期望的(。 也许这是编译器中的一个错误。 我将在更新版本的Scala上尝试一下,看看。

object Test extends App {
  case class Vector3D(x:Double, y:Double, z:Double)
  trait bFrame
  trait nFrame
  type bVector3D = Vector3D with bFrame
  type nVector3D = Vector3D with nFrame
  val p_b:bVector3D = new Vector3D(1.0, 2.0, 3.0) with bFrame  //Works
  //val p_b:bVector3D = Vector3D(1.0, 2.0, 3.0) with bFrame    //Doesn't work
  p_b match {
    case _:nVector3D => println("Vector in the n-Frame")
    case _:bVector3D => println("Vector in the b-Frame")      //Compiler says this is unreachable
    case _:Vector3D  => println("Vector in an undetermined frame")
    case _           => println("Something other than a vector")
  }
}

最新更新