Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.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_Constructor - Fatal编程技术网

scala:如何在自己的构造函数中获取类

scala:如何在自己的构造函数中获取类,scala,constructor,Scala,Constructor,我需要访问在它自己的构造函数中构造的对象的类(出于各种我认为与我的问题无关的详细原因) 我想要这样的东西 class Foo(val i:Int) class Bar extends Foo(this.getClass.getName.length) val b = new Bar println(b.i) 打印3(“条”。长度)。但事实并非如此。如果上面的代码在其他对象中,“this”指的是该对象。如果上面的代码不在其他对象中(仅在某个包中),编译器会向 error: this can be

我需要访问在它自己的构造函数中构造的对象的类(出于各种我认为与我的问题无关的详细原因)

我想要这样的东西

class Foo(val i:Int)
class Bar extends Foo(this.getClass.getName.length)
val b = new Bar
println(b.i)
打印3(“条”。长度)。但事实并非如此。如果上面的代码在其他对象中,“this”指的是该对象。如果上面的代码不在其他对象中(仅在某个包中),编译器会向

error: this can be used only in a class, object, or template
class Bar extends Foo(this.getClass.getName)
                      ^
澄清:我不能将Foo更改为在其主体中使用val而不是构造函数,因为Foo的API已经存在并且是固定的(因此,是的,我必须是构造函数参数)。它在构造函数时需要一个整数参数,但该整数只能通过访问该类来计算

(我知道上面的例子仍然愚蠢和堕落。如果人们关心,我可以详细解释为什么我需要在我真正的项目中上课,)


当然,编译器和运行时在构造过程中都知道要构造的对象的类。用什么语法可以得到它?(没有这样的语法吗?如果没有,我想知道为什么。我很惊讶,似乎没有一种简单、标准的方法来实现这一点。)

不确定这是否可能以干净的方式实现。如果你喜欢黑客,你可以做

class Bar extends Foo((new Exception).getStackTrace.apply(0).getClassName)

然而,我强烈地反对它

惰性val解决了这个问题:

object Early
{
    abstract class Foo { val name: String }

    class Bar extends Foo { lazy val name = getClass.getName }

    def
    main(args: Array[String]): Unit = {
        val b = new Bar
        println(b.name)
    }
}
收益率:

% scala Early
Early$Bar
那么这个呢:

  class Foo(otherName: Option[String] = None) {
    val name = otherName.getOrElse(this.getClass.getName)
  }
  class Bar extends Foo()
  val b = new Bar
  println(b.name)

你必须解释你想做这件事的动机。名称必须是
Foo
的构造函数参数,还是可以是抽象成员?它必须是
val
还是
def

你可以这样做

class Foo(val name: String)
class Bar extends Foo("") {
  override val name = getClass.getName
}
newbar()

但我怀疑,如果你的真正动机是已知的,那么有更好的方法来做你真正想做的事情。

怎么样


类Bar扩展了Foo(classOf[Bar].getName.length)

这似乎可以满足您的需求,而无需使用惰性val,也无需更改基类:

scala> class Base(val name: String)
defined class Base

scala> class Derived extends Base(classOf[Derived].getName)
defined class Derived

scala> new Derived name
res0: String = Derived

顺便说一句,名字
Early
是我第一次尝试使用“早期定义”结构来解决这个问题时留下的。Randal,谢谢你的回答。不幸的是,这对我来说不起作用,正如我编辑的问题中更好地描述的那样。这是我发布到StackOverflow的第一个问题。能这么快得到答案真是太好了。谢谢大家。然而,我现在明白了,我必须使我的示例更加复杂,以更好地反映我的真实用例。我想现在要做的是编辑我的问题。我现在就这么做。你意识到访问公共
val
仍然是通过(常规多态)方法进行的吗?@chrispy:谢谢你的建议,但是Geoff Reedy的回答对原始问题和稍微编辑的问题都起到了作用。他的回答现在被接受了。杰夫,谢谢你。这就成功了。它保留了Foo的原始API,同时允许使用this.getClass初始化val。我想Bar占用的内存量与Foo相同,但我不确定,我不知道如何验证。@mccallum您可以使用
javap-p classname
来显示类中的字段。在这种情况下,Foo和Bar中都会有一个值字段,因此有额外的存储空间。如果Foo的构造函数参数是一个对象,那么最好使用null作为参数,以最小化存储需求。