簡體   English   中英

Scala,覆蓋泛型類型的方法

[英]Scala, override method on generic type

我正在嘗試構建DSL ,此 DSL 上的方法之一是無參數的,並使用有界泛型類型。 今天我必須添加一個“功能”,理想情況下將使用相同的方法名稱。 但是,因為唯一的參數是通用參數,所以我不能用通常的方式覆蓋它。

是否有允許對不同泛型類型使用相同方法的技巧?

我的方法看起來像:

def ask[H <: Handler] = {
  new CommandBuilder[H]
}
class CommandBuilder[H <: Handler] {
  def toExecute[C <: H#C](command: C) = {
    //...
  }
} 

我想補充一點:

def ask[S <: State] = {
  new QueryBuilder[S]
}
class QueryBuilder[S <: State] {
  def toExecute[Q <: S#Q](query: Q) = {
    //...
  }
} 

我想在類型上模式匹配ClassTag但我需要強類型安全:

  • 不允許Query Handler ask[State] 必須返回 QueryBuilder
  • CommandQuery是唯一支持的類型。 ask的通用類型只能是HandlerState

也許你可以將你的代碼重構為這樣的東西?

sealed trait FooBar

sealed trait Foo extends FooBar {
  def process(i: Int): Int
}

object Foo {
  implicit final case object FooImpl extends Foo {
    override def process(i: Int): Int = i + 1
  }
}

sealed trait Bar extends FooBar {
  def process(s: String): String
}

object Bar {
  implicit final case object BarImpl extends Bar {
    override def process(s: String): String = s.toUpperCase
  }
}

object Test {
  trait FooBarPartiallyApplied[FB <: FooBar] {
    type Out
    def out: Out
  }

  object FooBarPartiallyApplied {
    type Aux[FB <: FooBar, _Out] = FooBarPartiallyApplied[FB] { type Out = _Out }

    implicit final def FooPartiallyAppliedBuilder[F <: Foo]: Aux[F, FooPartiallyApplied[F]] =
      new FooBarPartiallyApplied[F] {
        override final type Out = FooPartiallyApplied[F]

        override final val out: FooPartiallyApplied[F] =
          new FooPartiallyApplied[F](dummy = true)
      }

    implicit final def BarPartiallyAppliedBuilder[B <: Bar]: Aux[B, BarPartiallyApplied[B]] =
      new FooBarPartiallyApplied[B] {
        override final type Out = BarPartiallyApplied[B]

        override final val out: BarPartiallyApplied[B] =
          new BarPartiallyApplied[B](dummy = true)
      }

    final class FooPartiallyApplied[F <: Foo](private val dummy: Boolean) extends AnyVal {
      def toExecute(i: Int)(implicit foo: F): Int = foo.process(i)
    }

    final class BarPartiallyApplied[B <: Bar](private val dummy: Boolean) extends AnyVal {
      def toExecute(s: String)(implicit bar: B): String = bar.process(s)
    }
  }

  def ask[FB <: FooBar](implicit pa: FooBarPartiallyApplied[FB]): pa.Out =
    pa.out
}

它按預期工作:

Test.ask[Foo.FooImpl.type].toExecute(10)
// res: Int = 11

Test.ask[Foo.FooImpl.type].toExecute("blah")
// Type error.

Test.ask[Bar.BarImpl.type].toExecute(10)
// Type error.

Test.ask[Bar.BarImpl.type].toExecute("blah")
// res: String = "BLAH"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM