我正在尝试在Android项目中使用Kotlin.我需要创建自定义视图类.每个自定义视图都有两个重要的构造函数:
I'm trying to use Kotlin in my Android project. I need to create custom view class. Each custom view has two important constructors:
public class MyView extends View { public MyView(Context context) { super(context); } public MyView(Context context, AttributeSet attrs) { super(context, attrs); } }MyView(Context)用于实例化代码中的视图,当从XML扩展布局时,布局填充器会调用MyView(Context, AttributeSet).
MyView(Context) is used to instantiate view in code, and MyView(Context, AttributeSet) is called by layout inflater when inflating layout from XML.
回答此问题建议我将构造函数与默认值或工厂方法一起使用.但是,这就是我们拥有的:
Answer to this question suggests that I use constructor with default values or factory method. But here's what we have:
工厂方法:
fun MyView(c: Context) = MyView(c, attrs) //attrs is nowhere to get class MyView(c: Context, attrs: AttributeSet) : View(c, attrs) { ... }或
fun MyView(c: Context, attrs: AttributeSet) = MyView(c) //no way to pass attrs. //layout inflater can't use //factory methods class MyView(c: Context) : View(c) { ... }具有默认值的构造函数:
class MyView(c: Context, attrs: AttributeSet? = null) : View(c, attrs) { ... } //here compiler complains that //"None of the following functions can be called with the arguments supplied." //because I specify AttributeSet as nullable, which it can't be. //Anyway, View(Context,null) is not equivalent to View(Context,AttributeSet)如何解决这个难题?
更新:似乎我们可以使用View(Context, null)超类构造函数而不是View(Context),因此工厂方法似乎是解决方案.但是即使那样,我仍然无法使我的代码正常工作:
UPDATE: Seems like we can use View(Context, null) superclass constructor instead of View(Context), so factory method approach seems to be the solution. But even then I can't get my code to work:
fun MyView(c: Context) = MyView(c, null) //compilation error here, attrs can't be null class MyView(c: Context, attrs: AttributeSet) : View(c, attrs) { ... }或
fun MyView(c: Context) = MyView(c, null) class MyView(c: Context, attrs: AttributeSet?) : View(c, attrs) { ... } //compilation error: "None of the following functions can be called with //the arguments supplied." attrs in superclass constructor is non-null推荐答案
自M11(2015年3月19日发布)以来,Kotlin支持多个构造函数.语法如下:
Kotlin supports multiple constructors since M11 which was released 19.03.2015. The syntax is as follows:
class MyView : View { constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) { // ... } constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0) {} }更多信息此处和此处.
编辑:您还可以使用@JvmOverloads批注,以便Kotlin为您自动生成所需的构造函数:
Edit: you can also use @JvmOverloads annotation so that Kotlin auto-generates the required constructors for you:
class MyView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyle: Int = 0 ) : View(context, attrs, defStyle)但是要小心,因为这种方法有时可能会导致意外的结果,具体取决于您从中继承的类如何定义其构造函数. 该文章.
Beware, though, as this approach may sometimes lead to the unexpected results, depending on how the class you inherit from defines its constructors. Good explanation of what might happen is given in that article.
更多推荐
如何使用Kotlin创建自定义视图的构造函数
发布评论