【问题标题】:Scala class singleton with non-default constructor parameters具有非默认构造函数参数的 Scala 类单例
【发布时间】:2017-10-03 15:02:59
【问题描述】:

我已经阅读了有关从伴随类继承的对象的问题。

例如:

但我有一点不同的问题(我不确定这是一个错误)

我有以下代码:

class Scala(name: String)

import Scala._

object Scala extends Scala(TEST_NAME){
  val TEST_NAME = "test name"
}

注意,我使用的是在伴生对象范围内定义的变量,然后将其传递给 super 的构造函数。

我收到以下编译错误:

Scala.scala:5: error: super constructor cannot be passed a self reference 
unless parameter is declared by-name

object Scala extends Scala(TEST_NAME){
                           ^
one error found

我尝试过的其他变体:

按姓名呼叫:

class Scala(name: => String)

import Scala._

object Scala extends Scala(TEST_NAME){
  val TEST_NAME = "test name"
}

命名参数:

class Scala(name: String)

import Scala._

object Scala extends Scala(name = TEST_NAME){
  val TEST_NAME = "test name"
}

他们两个:

class Scala(name: => String)

import Scala._

object Scala extends Scala(name = TEST_NAME){
  val TEST_NAME = "test name"
}

一些环境细节:

  • java:java version "1.8.0_144"
  • javac:javac 1.8.0_144
  • 斯卡拉:Scala code runner version 2.12.3
  • scalac:Scala compiler version 2.12.3
  • 操作系统:Darwin ***.local 17.0.0 Darwin Kernel Version 17.0.0: Thu Aug 24 21:48:19 PDT 2017; root:xnu-4570.1.46~2/RELEASE_X86_64 x86_64

更新:

对于有兴趣解决此问题的任何人:

【问题讨论】:

  • 我认为陪伴在这里没有任何作用
  • @EduardoParejaTobes 你的意思是不需要陪伴,是吗?
  • 是的,这类似于stackoverflow.com/q/32203867/614394,但用于值。我认为这对类型来说很好,对值来说是错误的:)
  • 这样的好伙伴是有道理的。例如:scala.util.Random。或者当您有返回静态数据的 DTO 时,例如服务描述、使用条款等。
  • 我的意思不是同伴扩展他们所伴随的类/特征,而是关于在扩展任何其他类/特征时可以“访问自身”的对象。我认为它的类型应该是可访问的(这样你就可以写object X extends Y[X.type]),但它的值不是。

标签: scala constructor companion-object callbyname


【解决方案1】:

对于您的受限用例:

scala> class C(s: String) ; object X extends C(X.x) { final val x = "hello, world" }
defined class C
defined object X

常量值定义是内联的(根据规范)。

【讨论】:

    【解决方案2】:

    您可以使用将在 Scala 3 中删除的晦涩功能:早期初始化程序。它允许您在调用超类构造函数之前指定要运行的初始化代码。

    class Scala(name: String)
    
    object Scala extends {
      val TEST_NAME: String = "test name"
    } with Scala(TEST_NAME) { /* rest of object code */ }
    

    请注意,不需要导入 - TEST_NAME 已在范围内。


    这是一个Scastie snippet 来证明它有效。

    【讨论】:

    • 感谢您的回答。那么我的问题的解决方案是什么?它是一个错误吗?边缘案例?
    • @AndriiAbramov 我不知道。我会调用一个错误,即按名称参数不起作用,而消息表明它应该(尤其是如果旧版本的 Scala 支持它,我现在无法检查),但它可能也足够一个边缘情况,因为至少从 2.10 开始似乎没有人关心。
    【解决方案3】:

    如果上面的代码可以编译,那么你可以编写

    class A(val x: String)
    
    object B extends A(B.x_again) {
    
      val x_again = x
    }
    

    这当然不好看。

    【讨论】:

    • 是的,我同意它看起来有点奇怪。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 1970-01-01
    • 2017-11-10
    • 2017-09-27
    • 2011-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多