针对特殊情况F 对于F

问题描述 投票:0回答:1

在下面的最小示例中,Kotlin是否有任何方法可以通过将Foo保留为抽象来将BardefaultBar分开?

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")))
}

通过“分开”,我的意思是我想将FooBar放在两个完全独立的文件中,所以他们不要互相提及。方法foo应该是“硬”的,应该保留在Foo中。方法defaultBar应该是“简单的”,可以在任何地方实现。我想同时提及FooBar的唯一地方应该是一些单独的类,该类提供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")))
}

[不幸的是,科特林无法从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还不支持使用现场的下限类型。


((可选)我希望可以的]

下面的Scala代码段显示了我的意思:

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。>>


((可选)为什么我希望有可能

在这种特殊情况下不需要完整的HKT,因为我们只需要对单个类型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,即将FooFooImpl合并到一个大文件之外,还有什么可以做的?

在下面的最小示例中,Kotlin是否可以通过将defaultBar保留为抽象来将Foo与Bar分开?密封类Bar {数据类Hello (val who:X):Bar

generics kotlin types higher-kinded-types
1个回答
1
投票

您可以通过使用super扩展功能并写foo而不是B : P来模仿P super B

© www.soinside.com 2019 - 2024. All rights reserved.