构造函数在kotlin派生类中的可分构造器

这是我之前询问的一个问题的后续。 我使用https://github.com/nekocode/android-parcelable-intellij-plugin-kotlin上的Android Parcelable插件按照bennyl的建议,我将构造函数生成的代码更改为

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

这就摆脱了我所问过的语法错误。 我现在还有一个问题,一开始我就忽视了。

该插件为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() } 

(实际上,我添加了旋转的线条,但这不重要。)

现在,构造函数将不会编译。 this是强调,我看到的工具提示 在这里输入图像描述 我期望看到类似的东西,

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

但是如果我尝试这样做,我会收到消息:“超类构造函数被调用之前无法访问上下文”。 我对kotlin(和android)很新,我不明白这里发生了什么。 我试过调用super ,但它告诉我,主要构造函数的调用是预期的。 我也尝试调用TextView(),但它告诉我, thissuper的呼叫预计。

我没有看到有任何方法可以将上下文写入包裹(我不确定这意味着什么)。

你能告诉我代码应该如何修改,更重要的是,你能解释为什么吗?

context需要被提供来调用this(context,...)构造函数。 但是,由于Parcelable需要`构造函数(parcel:Parcel),所以不能将constructor(parcel: Parcel)更改为constructor(context: Context, parcel: Parcel) parcel:Parcel)

这是怎么回事? 你的类派生自需要Context实例化的TextView 。 你的主要constructor是这样做的…

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

文件说…

如果类有一个主构造函数,那么可以(并且必须)使用主构造函数的参数来初始化基类型。

由于您选择使用主构造函数,所以基类必须由该构造函数进行初始化,并且辅助构造函数将链接在主要构造函数之外。

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

你看到的错误是由于第二个二级构造函数没有提供一个上下文给它所调用的构造函数(它调用了第一个二级构造函数)。

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

更重要的是Parcel构造函数是在Parcelable接口添加到继承中时由Parcelable Plug-in工具添加的( 请参阅Parcelable实现的示例 )。 正因为如此, CREATOR方法(所需的Parcelable.Creator接口)期望找到一个构造函数,只需要一个Parcel 。 你可能不得不调整你的设计,因为Context是不可序列化的,因此不应该(不能)被放置在一个Parcel 。 你可以看看CREATOR代码,看看有关修改,但我会建议一个设计更改。

“最佳实践”是将您的业务逻辑与UI逻辑分开。 在这里你已经把你的ChessClock到一个UI对象TextView 。 一个“ChessClock”声音对我来说就像UI,所以也许你需要一个ChessClockData类作为一个Parcelable而不是Clock UI传递。