【问题标题】:How to pass class member to super classes constructor?如何将类成员传递给超类构造函数?
【发布时间】:2019-06-24 19:01:36
【问题描述】:

为什么不能将成员对象传递给超类构造函数?

这是有效的:


class Foo(private val whatever : Object = Object()) : BaseClass(whatever) {

    fun someFunction() {
        // Do something with "whatever"
        println(whatever.toString())
    }

}

但这不是:


class Foo() : BaseClass(whatever) {

    private val whatever = Object()

    fun someFunction() {
        // Do something with "whatever"
        println(whatever.toString())
    }

}

在第二个例子中,成员whatever 不能传递给基类。这是有道理的,因为子类是在基类之后初始化的,此时 whatever 还不存在。但为什么第一个示例有效?

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    在创建另一个类的子类时,您调用这些类的构造函数,例如BaseClass(whatever)。在这种情况下,需要在这些子类的主构造函数中创建/传递 whatever 对象作为参数。

    在 kotlin 中,除了在类中创建属性外,您还可以使用 var/val 在主构造函数中将其定义为参数。喜欢class Foo(val whatever : Object)

    但是,它只在主构造函数上。

    【讨论】:

    • 我知道可以在构造函数中创建属性;如第一个示例所示。但问题是,如何将属性移动到类内并仍将其传递给基类?
    【解决方案2】:

    问题是Initialization Order

    第一个示例有效,因为BaseClass 的构造函数的参数是Foo 的构造函数的参数。没有问题。参数刚刚通过。

    第二个示例不起作用,因为在初始化Foowhatever 属性之前,需要首先调用BaseClass 的构造函数。

    编辑:

    如果你真的需要在Foo内部初始化whatever,那么你可以使用Companion Object

    class Foo2() : BaseClass(whatever) {
    
        companion object {
            private val whatever = Object()
        }
    
    }
    

    【讨论】:

    • 但是在第一个示例中创建的对象whatever 在哪里?我怎样才能使第二个工作,以便whatever不是由子类构造函数设置?
    • 无论在构造函数之外创建什么,都可能使用它的默认值,但这仍然是在调用 BaseClass 之前。
    • 为什么你需要使用 Foo 中初始化的任何东西?为什么不直接把它传给 Foo 的构造函数呢?
    • 我在Foo的某些功能中需要它。
    • 我可以通过它并将 BaseClass 中的 whatever 设为 protected val,这样我就可以在 Foo 中访问它。也许这是最干净的解决方案..
    猜你喜欢
    • 1970-01-01
    • 2020-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-26
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    相关资源
    最近更新 更多