使用Scala特征标记类的实例

时间:2018-03-21 03:40:19

标签: scala types traits

我有一个表示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

在我尝试这个特征技巧之前,构造函数中的表达式求值为double,并且一切正常。我已经读到你可以将特征应用于类的实例,而不仅仅是类本身,但它似乎在这里工作。我得到的错误是"';'预期,但'与'发现&#34。我想使用类型系统来检查参考帧而无需修改原始类。有没有办法使这项工作?

2 个答案:

答案 0 :(得分:1)

评论中没有足够的空间来回答

  

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

是=)

示例:

$ 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;
...
你可以看到

- 匿名类初始化。

答案 1 :(得分:0)

我想我明白了。目前尚不清楚原因,但由于某些原因,Scala(截至2.12.2)并不希望您使用&#34; apply&#34;构建案例类的方法。我必须添加&#34; new&#34;使它工作。另外,我原本应该更清楚的是,Vector是一个案例类,它代表数学意义上的向量,而不是Scala集合。我在这里将其更改为Vector3D以使其更清晰。此外,2.12.2编译器表示在b-Frame&#34;中打印&#34; Vector的行。无法访问,但是当我运行它时,该行被执行(即输出是你期望的)。也许这是编译器中的一个错误。我将尝试使用更新版本的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")
  }
}