使用`functionName`的Scala方法定义:`dataType` =`functionName`

时间:2018-03-07 08:38:09

标签: scala

我遇到过这个新的方法定义。需要解释这里到底发生了什么。

父母特质

sealed trait Generic{
 def name : String = name  // what is the body of this function call?
 def id : Int = id         
 def place : String = place
}

儿童案例类

case class Capital( 
  countryName : String, 
  override val id: Int, 
  override val place:String
) extends Generic
  • warning: method place in trait Generic does nothing other than call itself recursively我收到此警告信息,使用这些类型的方法有什么不对吗?
  • 编译器如何处理这些类型的函数调用def name : String = name
  • 此调用是否将其正文视为其方法名称?

2 个答案:

答案 0 :(得分:0)

好的,所以在你的trait中通过递归定义方法体。意味着这些方法,如果不被覆盖(并且它们不应该以某种方式定义它们),将递归调用自身直到StackOverflowError发生。例如,您没有覆盖name中的Capital方法,因此在这种情况下,您会在运行时获得StackOverflowError

val c = Capital("countryName", 1, "place")
c.name

所以,你被警告,你有递归定义。特性是sealed,所以至少它不能在其他地方被覆盖,但无论如何,这样的定义就像是在你的道路上放置地雷并依靠你的记忆,你不会忘记它们(其他任何人都会要小心,在扩展之前检查trait定义

答案 1 :(得分:0)

您在特征中提供了无限循环的默认实现,非常类似于以下示例:

def infiniteLoop: Unit = infiniteLoop

这可以说是你可能放在特征方法中的最无用和最危险的代码。你只能通过使它变得不确定而使它变得更糟。幸运的是,编译器会给你一个非常明确和准确的警告:

  

警告:特征中的方法位置Generic除递归调用本身外什么都不做

  • “使用这些类型的方法有什么不对”?:在您的代码中使用非生产性无限循环通常被认为是错误的,除非您的目标是使用计算机硬件产生尽可能多的热量
  • “编译器如何处理这些类型的函数调用”?:就像任何其他尾递归函数一样,但另外它输出上面的警告,因为它看到它显然不是你想要的
  • “此调用是否将其正文视为其方法名称?”:每个方法声明的正文都在= - 符号后面。在你的情况下,省略了函数体周围常见的花括号,整个函数体只包含对它自身的递归调用。

如果您不希望有任何不必要的无限循环,只需将方法保持未实现状态:

sealed trait Generic{
  def name: String
  def id: Int
  def place: String
}

这还有一个额外的好处,即如果您忘记在子类中实现这些方法之一,编译器可以发出警告。