在Kotlin派生类中采用可组装构造函数的构造函数

在Kotlin派生类中采用可组装构造函数的构造函数

本文介绍了在Kotlin派生类中采用可组装构造函数的构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我先前问的问题的后续内容.我正在使用 https://github.com/nekocode/android-parcelable-intellij-plugin-kotlin 按照bennyl的建议,我将为构造函数生成的代码更改为

This is a followup to a question I asked earlier. I am using the Android Parcelable plugin from https://github.com/nekocode/android-parcelable-intellij-plugin-kotlinFollowing bennyl's suggestion, I changed the generated code for the constructors to

class ChessClock(context:Context) : TextView(context), Parcelable {
    lateinit var player:String
    constructor(context:Context, p:String, angle:Float) : this(context) {
        player = p
        rotation = angle
    }
}

,这摆脱了我所问过的语法错误.现在,我遇到了另一个我首先忽略的问题.

and this got rid of the syntax errors I had asked about. I now have another problem that I overlooked at first.

插件为writeToParcel生成了以下代码:

The plugin generated this code for writeToParcel:

override fun writeToParcel(parcel: Parcel, flags: Int) {
    parcel.writeString(player)
    parcel.writeFloat(rotation)
    parcel.writeLong(mTime)
    parcel.writeInt(mState)
}

和该构造函数:

constructor(parcel: Parcel) :this() {
    player = parcel.readString()
    rotation = parcel.readFloat()
    mTime = parcel.readLong()
    mState = parcel.readInt()
}

(实际上,我添加了带有旋转的行,但这并不重要.)

(Actually, I added the lines with rotation, but that's unimportant.)

现在,构造函数将无法编译. this带下划线,我看到工具提示我希望看到类似

Now, the constructor won't compile. this is underlined and I see the tooltipI would expect to see something like,

constructor(parcel: Parcel) :this(context, parcel.readString(), parcel.readFloat()) {
    mTime = parcel.readLong()
    mState = parcel.readInt()
}

但是,如果我尝试这样做,则会收到消息在调用超类构造函数之前无法访问上下文".我对Kotlin(和android)很陌生,我不明白这里发生了什么.我试过调用super,但是它告诉我应该调用主构造函数.我还尝试了调用TextView(),但它告诉我应该调用thissuper.

but if I try that, I get the message, "Cannot access context before superclass constructor has been called." I'm pretty new to kotlin (and android) and I don't understand what's happening here. I've tried invoking super, but it tells me that a call to the primary constructor is expected. I've also tried invoking TextView() but it tells me that a call to this or super is expected.

我看不到有一种将上下文写入包裹的方法,(我不确定这是什么意思.)

I don't see that there is a way to write the context to the parcel, (and I'm not sure what this would mean.)

可以告诉我如何修改代码,更重要的是,您可以解释原因吗?

Can you tell me how the code should be modified, and more important, can you explain why?

推荐答案

context以便调用this(context,...)构造函数.但是,您不能将constructor(parcel: Parcel)更改为constructor(context: Context, parcel: Parcel),因为Parcelable需要`constructor(parcel:Parcel)

context needs to be supplied in order to call the this(context,...) constructors. But, you cannot change your constructor(parcel: Parcel) to constructor(context: Context, parcel: Parcel) because Parcelable requires the `constructor(parcel: Parcel)

这是怎么回事?您的类是从TextView派生的,它需要Context进行实例化.您的主要constructor正在这样做...

What's going on? Your class derives from TextView which requires a Context to instantiate. Your primary constructor is doing that...

class ChessClock(context: Context) : TextView(context) ...

文档说...

由于已选择使用主构造函数,因此必须由该构造函数初始化基类,并且将辅助构造函数链接到主构造函数.

Since you've chosen to use a primary constructor, the base class must be initialized by that constructor, and the secondary constructors chain off of the primary.

    constructor(context:Context, p:String, angle:Float) : this(context) ...
    // notice how the secondary constructor has the context with which to
    // call the primary constructor

您看到的错误是由于第二个辅助构造函数未向其正在调用的构造函数提供上下文(正在调用第一个辅助构造函数).

The error you are seeing is due to the second secondary constructor not supplying a context to the constructor that it is calling (it's calling the first secondary constructor).

    constructor(parcel: Parcel) :this(context, parcel.readString(), parcel.readFloat()) ...
    // compiler error because "context" has no source, there is no
    // parameter "context" being supplied

更重要的是,当将Parcelable接口添加到继承中时,Parcelable插件工具添加了Parcel构造函数(请参阅Parcelable实现的示例).因此,CREATOR方法(必需的Parcelable.Creator接口)期望找到仅采用Parcel的构造函数.您可能必须调整设计,因为Context不可序列化,因此不应(不能)放置在Parcel中.您可以查看CREATOR代码并查看有关对其进行修改的信息,但我建议您进行设计更改.

More importantly, the Parcel constructor was added by the Parcelable Plug-in tool when it added Parcelable Interface to the inheritance (see the example of a Parcelable implementation). And as such, the CREATOR method (the required Parcelable.Creator Interface) expects to find a constructor that takes only a Parcel. You may have to adjust your design, because a Context is not serializable and therefore should not (cannot) be placed in a Parcel. You could look at the CREATOR code and see about modifying that, but I would recommend a design change.

最佳做法"是将业务逻辑与UI逻辑分开.在这里,您已将ChessClock绑定到UI对象TextView.在我看来,"ChessClock"听起来像UI,所以也许您需要一个ChessClockData类作为Parcelable而不是Clock UI来传递.

"Best practice" is to separate your business logic from your UI logic. Here you have tied your ChessClock to a UI object TextView. A "ChessClock" sound to me like UI, so maybe you need a ChessClockData class to pass around as a Parcelable instead of the Clock UI.

这篇关于在Kotlin派生类中采用可组装构造函数的构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-18 14:20