Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.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 案例对象扩展特征的行为差异_Scala - Fatal编程技术网

Scala 案例对象扩展特征的行为差异

Scala 案例对象扩展特征的行为差异,scala,Scala,我正在github上查看一个scala项目来学习scala,这时我遇到了Case1片段。trait扩展Scala产品trait,然后case对象扩展该trait。这个编译得很好。 为了更好地理解这一点,我尝试了Case2,它似乎没有编译,它要求我在case对象中定义absMethod()。 我不明白为什么在第一种情况下不会发生这种情况 //Case 1 sealed abstract trait test1 extends Product with Serializable case objec

我正在github上查看一个scala项目来学习scala,这时我遇到了
Case1
片段。trait扩展Scala
产品
trait,然后case对象扩展该trait。这个编译得很好。 为了更好地理解这一点,我尝试了
Case2
,它似乎没有编译,它要求我在case对象中定义
absMethod()
。 我不明白为什么在第一种情况下不会发生这种情况

//Case 1
sealed abstract trait test1 extends Product with Serializable
case object test11 extends test1
test11.productArity  

//Case 2  
trait abstact extends Any{
  def absMethod():Int
}  
sealed abstract trait test2 extends abstact
case object test22 extends test2
test22.absMethod()

这是因为
case对象是具体的,需要实现其抽象父类。例如,这将起作用并打印
42

trait Abstract {
  def method(): Int
}  

sealed trait Test2 extends Abstract

case object Test22 extends Test2 {
  def method(): Int = 42
}

Test22.method()

对于第一种情况,
case类
es和
case对象
s是
Product
s,它们的字段在编译时生成。例如,一个带有两个字段的
case类
也是一个带有算术2的
产品
,就像一个
Tuple2[a,B]
(a,B)
,一对)。

这是因为
case对象
是具体的,需要有其抽象父类的实现。例如,这将起作用并打印
42

trait Abstract {
  def method(): Int
}  

sealed trait Test2 extends Abstract

case object Test22 extends Test2 {
  def method(): Int = 42
}

Test22.method()

对于第一种情况,
case类
es和
case对象
s是
Product
s,它们的字段在编译时生成。例如,一个带有两个字段的
案例类
也是一个具有算术2的
产品
,就像
Tuple2[a,B]
(a,B)
,一对)。

第一个案例是编译的,因为编译器对案例类/对象具有
产品性
的特殊知识。作为编译过程的一部分,它不仅会创建一个伴生对象(用于case类),还会实现多种方法,例如
equals
hashCode
productArity
(以及更多)

如果在打字机阶段之后查看第一次测试的输出(
scalac-Xprint:typer
):

sealed abstract trait test1使用可序列化的产品扩展AnyRef;
案例对象test11使用com.github.yuvalitzchakov.TupleTest.test1和可序列化的产品扩展AnyRef{
def():com.github.yuvalitzchakov.TupleTest.test11.type={
测试11.super.();
()
};
覆盖def productPrefix:String=“test11”;
def生产率:Int=0;
def productElement(x$1:Int):任意=x$1匹配{
case=>抛出新的IndexOutOfBoundsException(x$1.toString())
};
重写def productIterator:Iterator[Any]=scala.runtime.ScalaRunTime.typedProductIterator[Any](test11.this);
def canEqual(x$1:Any):Boolean=x$1.$isInstanceOf[com.github.yuvalitzchakov.TupleTest.test11.type]();
覆盖def hashCode():Int=-877171150;
重写def toString():String=“test11”;
private def readResolve():Object=com.github.yuvalitzchakov.TupleTest.test11
}

您可以看到编译器如何实现
productArity
并分配
0
(因为对象没有构造函数参数),这在
Product
上是抽象的。对于自定义的抽象方法,您必须自己填充它,因此编译器在找不到实现时会抱怨。

第一种情况是编译的,因为编译器对案例类/对象的
生产性有专门的了解。作为编译过程的一部分,它不仅会创建一个伴生对象(用于case类),还会实现多种方法,例如
equals
hashCode
productArity
(以及更多)

如果在打字机阶段之后查看第一次测试的输出(
scalac-Xprint:typer
):

sealed abstract trait test1使用可序列化的产品扩展AnyRef;
案例对象test11使用com.github.yuvalitzchakov.TupleTest.test1和可序列化的产品扩展AnyRef{
def():com.github.yuvalitzchakov.TupleTest.test11.type={
测试11.super.();
()
};
覆盖def productPrefix:String=“test11”;
def生产率:Int=0;
def productElement(x$1:Int):任意=x$1匹配{
case=>抛出新的IndexOutOfBoundsException(x$1.toString())
};
重写def productIterator:Iterator[Any]=scala.runtime.ScalaRunTime.typedProductIterator[Any](test11.this);
def canEqual(x$1:Any):Boolean=x$1.$isInstanceOf[com.github.yuvalitzchakov.TupleTest.test11.type]();
覆盖def hashCode():Int=-877171150;
重写def toString():String=“test11”;
private def readResolve():Object=com.github.yuvalitzchakov.TupleTest.test11
}

您可以看到编译器如何实现
productArity
并分配
0
(因为对象没有构造函数参数),这在
Product
上是抽象的。对于自定义的抽象方法,您必须自己填充,因此编译器在找不到实现时会抱怨。

是的,我知道,但我不明白为什么在第一种情况下我没有看到任何错误。对不起,我没有正确回答问题。添加了一个澄清,希望这有帮助。是的,我知道,但我不明白为什么在第一种情况下,我没有看到任何错误。对不起,我没有得到正确的问题。添加了一个澄清,希望这有帮助。谢谢你的问题,我发布了一个答案,希望能澄清你的疑问。除此之外,还有一些关于代码的注意事项:您不必显式扩展
Any
(一个扩展“nothing”的类隐式扩展
Any
),也不必将
trait
注释为
abstract
。这是不正确的。当类、特征或对象没有显式扩展任何内容时,它会自动扩展
AnyRef
。如果您有一个扩展了
AnyVal
的类,并且希望它从trait继承,那么该trait需要显式扩展
Any
。谢谢