编写一个具有与构造函数相同的默认值的函数

问题描述

抽象问题

请考虑以下内容

data class Data(val i: Int,val s: String = "")

fun <A1,A2,D> make(ctor: KFunction2<A1,D>,sideEffect: (D) -> D) =
    { a1: A1,a2: A2 -> sideEffect(ctor(a1,a2)) }

val makeData = make(::Data) {
    it.also { println("Side effect: i=${it.i},s=${it.s}") }
}
 

我可以使用所有构造函数参数调用makeData以获取 Data的实例,并且也带来一些副作用。但是,我 不能忽略参数,而使用构造函数认值:

val d1 = makeData(42,"hi")
val d2 = makeData2(42) // Error: No value passed for parameter 'p2'

如何重写通用make,使其输出为具有认值的函数

我要实现的目标

使用Kotlin React,我可以像这样声明属性

external interface VideoListProps: RProps { var videos: List<Video> }

要使用render()中的组件,我可以编写:

child(VideoList::class) { attrs.videos = unwatchedVideos }

我不喜欢这样做有以下三个原因:(a)使用组件比TypeScript / TSX更为冗长, (b)属性应声明为var,而属性应为只读(val),(c)没有强制要求实际上声明了成员;即使Props接口未将props.videos声明为可为空,也可能在运行时以null的形式出现。

Kotlin React的教程建议对接收器使用lambda,如下所示:

fun RBuilder.videoList(handler: VideoListProps.() -> Unit): ReactElement {
    return child(VideoList::class) {
        this.attrs(handler)
    }
}

现在我可以像这样使用组件了:

videoList { videos = unwatchedVideos }

虽然调用站点现在看起来更加简洁,但是我现在必须针对我编写的每个组件复制/粘贴并修改lambda代码段。这比TypeScript更为冗长,在TypeScript中,我不需要这种构造。此外,由于this现在指向RProps,所以videoList lambda无法访问RBuilder的其他成员。因此,如果我需要定义一个React key,我很茫然,需要使用以前的child(...)语法。最后,上面的问题(c)仍然存在。

为了使它更好,我编写了以下帮助程序结构:

fun <P : RProps,A1> RBuilder.childWithProps(
    klass: KClass<out Component<P,*>>,ctor: KFunction1<A1,P>
) =
    { a1: A1,handler: RHandler<P> -> child(klass.rClass,ctor(a1),handler) }

fun <P : RProps,A1,A2> RBuilder.childWithProps(
    klass: KClass<out Component<P,ctor: KFunction2<A1,a2: A2,ctor(a1,a2),handler) }

// more for KFunction3,KFunction4,... up to a reasonable amount of members,e.g. 16

我承认这也很丑,但是我只需要写一次。现在,我可以像这样声明道具(注意val而不是var):

data class VideoListProps(val videos: List<Videos>) : RProps

每个组件的附加代码现在更加简洁:

val RBuilder.videoList get() = childWithProps(VideoList::class,::VideoListProps) 

并像这样使用它:

videoList(watchedVideos) { /* you can set React key or children here if needed */ }   

如果我忘记设置所有属性,Kotlin现在将其标记错误。 现在所有内容看起来都很简洁,我编写的代码甚至比TypeScript / TSX少。剩下的唯一问题是,现在我总是必须传递所有成员,因为数据构造函数的任何认值在包装器中仍然是必需的。 这是实际的问题。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...