Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala中的Trait与抽象类_Scala - Fatal编程技术网

Scala中的Trait与抽象类

Scala中的Trait与抽象类,scala,Scala,假设没有多重继承,也不关心与Java的互操作性,下面的两个声明是否相等 sealed trait Foo { def x: Int } case object Bar extends Foo { val x = 5 } 及 不,这些不是等效的,可能会导致以后初始化顺序出现问题。我向每一行添加了完全相同的代码,表明它们从来都不是相等的代码块 sealed trait Foo { def x: Int val calc = x * 5 / 2 //at the time this

假设没有多重继承,也不关心与Java的互操作性,下面的两个声明是否相等

sealed trait Foo { def x: Int }
case object Bar extends Foo { val x = 5 }


不,这些不是等效的,可能会导致以后初始化顺序出现问题。我向每一行添加了完全相同的代码,表明它们从来都不是相等的代码块

sealed trait Foo {
    def x: Int
    val calc = x * 5 / 2  //at the time this runs, x is actually 0
  }
  case object Bar extends Foo {
    val x = 5

  }


  sealed abstract class Foo2(x: Int){
    val calc = x * 5 / 2
  }
  case object Bar2 extends Foo2(5)

  println(Bar.calc)
  println(Bar2.calc)

  //output  0  12 

首先,对代码进行一些修改(见下文)。我删除了
案例
,因为它与此处无关。我还在
Foo2
的构造函数中添加了
val
,因为
x
Bar2
中无法访问

sealed trait Foo { def x: Int }
object Bar extends Foo { val x = 5 }

sealed abstract class Foo2(val x: Int)
object Bar2 extends Foo2(5)

object Main {
  def main(args: Array[String]) : Unit = {
    println( Bar.x )
    println( Bar2.x )
  }
}
以下两个声明是否相等

sealed trait Foo { def x: Int }
case object Bar extends Foo { val x = 5 }
我们需要定义equal的含义:

  • 相等的wrt。一般结构:。trait不是一个抽象类。trait可以没有构造函数参数,而类可以。另一方面,一个类或对象(这里
    Bar2
    )只能从一个(抽象)类派生,而它可以混合在多个特征中。这里对traits和抽象类做了一个很好的比较:如果你需要决定traits还是class
  • 相等的wrt。字节码:。只要运行
    javap-v
    就可以说服自己
  • 相等的wrt<代码>条形图和
    Bar2
    仅限:。两者都可以相同地访问和使用。两者都是单例,它们公开了一个从外部可读(但不可写)的成员变量
    x
另外,
scalac-print
的输出非常有助于了解发生了什么:

sealed abstract trait Foo extends Object {
  def x(): Int
};
object Bar extends Object with com.Foo {
  private[this] val x: Int = _;
  <stable> <accessor> def x(): Int = Bar.this.x;
  def <init>(): com.Bar.type = {
    Bar.super.<init>();
    Bar.this.x = 5;
    ()
  }
};
sealed abstract class Foo2 extends Object {
  <paramaccessor> private[this] val x: Int = _;
  <stable> <accessor> <paramaccessor> def x(): Int = Foo2.this.x;
  def <init>(x: Int): com.Foo2 = {
    Foo2.this.x = x;
    Foo2.super.<init>();
    ()
  }
};
object Bar2 extends com.Foo2 {
  def <init>(): com.Bar2.type = {
    Bar2.super.<init>(5);
    ()
  }
};
object Main extends Object {
  def main(args: Array[String]): Unit = {
    scala.this.Predef.println(scala.Int.box(Bar.x()));
    scala.this.Predef.println(scala.Int.box(Bar2.x()))
  };
  def <init>(): com.Main.type = {
    Main.super.<init>();
    ()
  }
}
Foo扩展对象{
def x():Int
};
对象栏使用com.Foo扩展对象{
private[this]valx:Int=\uux;
def x():Int=Bar.this.x;
def():com.Bar.type={
超级酒吧(;
Bar.x=5;
()
}
};
密封抽象类Foo2扩展对象{
private[this]valx:Int=\uux;
def x():Int=Foo2.this.x;
def(x:Int):com.Foo2={
Foo2.this.x=x;
二、超级(;
()
}
};
对象Bar2扩展了com.Foo2{
def():com.Bar2.type={
Bar2.超级(5);
()
}
};
对象主扩展对象{
def main(参数:数组[字符串]):单位={
scala.this.Predef.println(scala.Int.box(Bar.x());
scala.this.Predef.println(scala.Int.box(Bar2.x()))
};
def():com.Main.type={
Main.super.();
()
}
}

我读过该线程的可能重复,我是从纯行为的角度来询问这个特定的例子。我不是Scala专家,但我会假设它们需要等效,就像进行等效比较一样(对于这个具体的例子)Java中的一个抽象类和一个接口。请注意,在抽象类示例中,您需要
val x:Int
,否则它只是未使用的构造函数参数,在调用
Bar.x
@ukasz时,会导致“error:value x不是object Bar的成员”!谢谢你指出这一票,因为答案不够全面。其次,初始化命令需要特别小心,但与user2066880给出的情况无关。