微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

抽象问题

请考虑以下内容

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.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?