作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在以下最小示例中,Kotlin中是否有任何方法可以通过将Foo
保留为抽象来将Bar
与defaultBar
分开?
sealed class Bar<out X> {
data class Hello<X>(val who: X): Bar<X>()
object Empty : Bar<Nothing>()
}
interface Foo {
fun defaultBar(): Bar<Nothing> = Bar.Empty
fun <P> foo(bar: Bar<P> = defaultBar()): Bar<P> = bar
}
fun main(args: Array<String>) {
println((object : Foo{}).foo(Bar.Hello("world")))
}
所谓“分开”,是指我希望
Foo
和
Bar
放在两个完全独立的文件中,因此它们不要互相提及。方法
foo
应该是“硬”的,应该保留在
Foo
中。
defaultBar
方法应该是“简单的”,可以在任何地方实现。我想同时提及
Foo
和
Bar
的唯一地方应该是一些单独的类,该类提供
defaultBar
的具体实现。
sealed class Bar<out X> {
data class Hello<X>(val who: X): Bar<X>()
object Empty : Bar<Nothing>()
}
interface Foo<B>{
fun <P: B> defaultB(): P
fun <P: B> foo(bar: P = defaultB()): P = bar
}
object FooImpl : Foo<Bar<Any>> {
override fun <P: Bar<Any>> defaultB(): P = Bar.Empty
}
fun main(args: Array<String>) {
println(FooImpl.foo(Bar.Hello("world")))
}
不幸的是,Kotlin无法从
Bar<out X>
的
P subtypeOf Bar<Any>
和
Bar<Nothing> subtypeOf P
派生。
sealed class Bar<out X> {
data class Hello<X>(val who: X): Bar<X>()
object Empty : Bar<Nothing>()
}
interface Foo<B, N: B> {
fun defaultBar(): N
fun <P : B super N> foo(bar: Bar<P> = defaultBar()): Bar<P> = bar
}
object FooImpl : Foo<Bar<Any>, Bar<Nothing>> {
fun defaultBar(): Bar<Nothing> = Bar.Empty
}
fun main(args: Array<String>) {
println(FooImpl.foo(Bar.Hello("world")))
}
,因为除了不支持HKT外,Kotlin还不支持使用现场的下限字体。
sealed trait Bar[+X]
case class Hello(who: String) extends Bar[String]
case object Empty extends Bar[Nothing]
trait Foo {
val defaultBar: Bar[Nothing] = Empty
def foo[P](bar: Bar[P] = defaultBar): Bar[P] = bar
}
println((new Foo{}).foo(Hello("world")))
可以重构为:
import language.higherKinds
sealed trait Bar[+X]
case class Hello(who: String) extends Bar[String]
case object Empty extends Bar[Nothing]
trait Foo[B[+_]] {
val defaultB: B[Nothing]
def foo[P](b: B[P] = defaultB): B[P] = b
}
object FooImpl extends Foo[Bar] {
val defaultB: Bar[Nothing] = Empty
}
println(FooImpl.foo(Hello("world")))
因此
Foo
在任何地方都不会提及
Bar
。
Bar
类型的
Nothing
求值:
sealed trait Bar[+X]
case class Hello(who: String) extends Bar[String]
case object Empty extends Bar[Nothing]
trait Foo[N] {
val defaultBar: N
def foo[P >: N](bar: P = defaultBar): P = bar
}
object FooInstance extends Foo[Bar[Nothing]] {
val defaultBar = Empty
}
println(FooInstance.foo(Hello("world")))
如果没有更高的种类,这可以工作,Java的
super
就足够了。但是,如上所述,Kotlin在使用站点似乎没有
>:
/
super
/下限类型。
foo
移至
FooImpl
之外(即将
Foo
和
FooImpl
合并到一个大文件中),还有什么可以做的?
最佳答案
您可以通过使super
扩展功能并编写foo
而不是B : P
来模仿P super B
:
sealed class Bar<out X> {
data class Hello<out X>(val who: X) : Bar<X>()
object Empty : Bar<Nothing>()
}
interface Foo<out B> {
fun defaultBar(): B
}
fun <B : P, P> Foo<B>.foo(bar: P = defaultBar()): P = bar
object FooImpl : Foo<Bar<Nothing>> {
override fun defaultBar(): Bar<Nothing> = Bar.Empty
}
fun main() {
println(FooImpl.foo(Bar.Hello("world")))
}
关于generics - 针对F <out X>的特定情况F <Nothing>缺少HKT的解决方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59056049/
我正在尝试使 Iteratee 结构通用,这样我就可以传入不同的解析函数并获得不同的 Iteratee。这是有效的非通用版本: use std::io::{BufRead, BufReader}; u
在Haskell 中,当使用typeclass 时,很容易声明其“实例”类型种类的约束。 class Functor (f :: * -> *) where ... * -> * 表示 HKT(H
如何在 Scala 中定义 HKT 来提供方法,例如 map,作为实例方法而不是对象函数? 我知道你可以 trait M[F[_]] { def map[A, B](f: F[A])(fn: A
我是一名优秀的程序员,十分优秀!