【问题标题】:Class Instantiation returns a Function objects类实例化返回一个函数对象
【发布时间】:2018-03-20 10:52:22
【问题描述】:

我试图理解当我创建扩展一个我认为扩展 Function0 [() => Unit] 的 Trait 的类时,为什么该类的对象的实例化是 Function0 类型?在对象实例化期间,apply 方法是否作为构造函数调用?我无法完全理解以下代码的机制。

scala> trait Base extends (() => Unit) {
 |
 |    def label: String
 | }
defined trait Base

scala> class Extend extends Base{
 | override def label = "Hello label"
 | override def apply()= println ("This is apply")
 |
 | }
defined class Extend

scala> val m = new Extend
m: Extend = <function0>

scala> m()
This is apply

【问题讨论】:

    标签: scala


    【解决方案1】:

    &lt;function0&gt;-thing 不是类型。这只是Function0 上定义的默认toString 方法的输出。您不会在任何地方覆盖toString,因此它使用超类的实现。添加像label 这样的方法不会改变任何东西,编译器无法读取(你的想法)。

    小演示:

    scala> val f = new Function0[Int]{ def apply(): Int = 42 }
    f: () => Int = <function0>
    
    scala> f.toString
    res0: String = <function0>
    

    另一方面,您示例中的 type 正确显示为 Extend

    【讨论】:

    • 谢谢@Andrey,但我想知道为什么new Extend 是Function0 类型是因为Extend extends Base extends Function0?另外,不是&lt;function0&gt; 不应该是Extend@&lt;randomnumber&gt; 来表示类的对象吗?
    • @jjayadeep new Extend 的类型为 Extend。而 repl 恰恰表明:m: Extend。因为你刚刚子类化了Function0Extend 也恰好是Function0 的子类型,我不确定你对它有什么惊讶?
    • 好的,我明白了 = 表示是因为 toString 方法。通常,当我们在 REPL 中创建新类时,它会给出一个对象引用,显示为 Class@number,我相信这是 AnyRef 的 toString 方法,但在这种情况下,它使用来自 Function0 的 toString。
    • @jjayadeep 它提供的内容取决于已经提供的toString-方法...例如,case-classes 通常会产生更好的人类可读输出,没有任何hash-numbers 等。我认为您只是混淆了 repl 的 result: Type = ToString 输出中的 TypeToString 部分,但现在这似乎很清楚了。
    • @jjayadeep ...并且构造函数不调用apply。它根本与构造函数无关。 apply 只是一个常用的方法,除了它有一些语法糖:m() 脱糖成m.apply()
    猜你喜欢
    • 1970-01-01
    • 2010-11-07
    • 1970-01-01
    • 2020-11-19
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    相关资源
    最近更新 更多