Scala 用隐式简化卷积码

Scala 用隐式简化卷积码,scala,Scala,我正在写一段代码,我觉得它变得非常复杂 我有一个API,它接受一个特性参数。这种特性可以通过许多类型实现。此外,这些类中的每一个都需要由专门的处理器处理 例如,我在下面创建了一个名为Context的特性,它有两种实际类型的MobileContext和WebContext 假设MobileContext和WebContext的记录方式不同,我们有ContextWriter[MobileContext]和ContextWriter[WebContext]形式的专门实现 要求方法应该是泛型的,但它应该

我正在写一段代码,我觉得它变得非常复杂

我有一个API,它接受一个特性参数。这种特性可以通过许多类型实现。此外,这些类中的每一个都需要由专门的处理器处理

例如,我在下面创建了一个名为Context的特性,它有两种实际类型的MobileContext和WebContext

假设MobileContext和WebContext的记录方式不同,我们有ContextWriter[MobileContext]和ContextWriter[WebContext]形式的专门实现

要求方法应该是泛型的,但它应该能够根据trait的实际类型将调用分派给正确的ContextWriter

这是我的密码

trait Context
case class WebContext(name: String) extends Context
case class MobileContext(name: String) extends Context


trait ContextWriter[T] {
   def log(message: String, context: T) : Unit
}

object ContextWriterUtil {
   def log[T](message: String, context: T)(implicit writer: ContextWriter[T]) = {
      writer.log(message, context)
   }
}

object ContextWriterImplicits {
   implicit val webImpl = new ContextWriter[WebContext] {
      override def log(message: String, context: WebContext) = println(s"I am in web context ${context} and the message is ${message}")
   }
   implicit val mobileImpl = new ContextWriter[MobileContext] {
      override def log(message: String, context: MobileContext) = println(s"I am in mobile context ${context} and the message is ${message}")
   }
   implicit val baseImpl = new ContextWriter[Context] {
      override def log(message: String, context: Context) = context match {
         case s: WebContext => {
            val writer = implicitly[ContextWriter[WebContext]]
            writer.log(message, s)
         }
         case s: MobileContext => {
            val writer = implicitly[ContextWriter[MobileContext]]
            writer.log(message, s)
         }
         case _ => throw new Exception("don't understand this type")
      }
   }
}

import ContextWriterImplicits._
object MyApplication extends App {

   // this is the generic method.
   def call[T <: Context](message: String)(implicit context: T) = {
      val actualContext = implicitly[Context]
      ContextWriterUtil.log(message, actualContext)
   }
   def web() = {
      implicit val webContext = WebContext("web")
      call("I am calling the method")
   }
   def mobile() = {
      implicit val mobileContext = MobileContext("mobile")
      call("I am calling the method")
   }
   web()
   mobile()
}
trait上下文
案例类WebContext(名称:String)扩展了上下文
案例类MobileContext(名称:String)扩展了上下文
特征上下文作者[T]{
def日志(消息:字符串,上下文:T):单位
}
对象ContextWriterUtil{
def log[T](消息:字符串,上下文:T)(隐式编写器:ContextWriter[T])={
writer.log(消息、上下文)
}
}
对象ContextWriterImplicits{
隐式val webImpl=new ContextWriter[WebContext]{
重写def log(message:String,context:WebContext)=println(s“我在web上下文${context}中,消息是${message}”)
}
隐式val mobileImpl=新上下文编写器[MobileContext]{
重写def log(message:String,context:MobileContext)=println(s“我在移动上下文${context}中,消息是${message}”)
}
隐式val baseImpl=new ContextWriter[Context]{
覆盖def日志(消息:字符串,上下文:上下文)=上下文匹配{
案例s:WebContext=>{
val writer=隐式[ContextWriter[WebContext]]
writer.log(消息,s)
}
案例s:MobileContext=>{
val writer=隐式[ContextWriter[MobileContext]]
writer.log(消息,s)
}
case=>抛出新异常(“不理解此类型”)
}
}
}
导入ContextWriterImplicits_
对象MyApplication扩展应用程序{
//这是通用方法。

def调用[TTLDR:从代码中删除继承

我不明白为什么您需要
baseImpl:ContextWriter[Context]
,只需删除此隐式,并始终要求更精确的上下文。
call
变成:

def call[T: ContextWriter](message: String)(implicit context: T) = {
   ContextWriterUtil.log(message, context)
}
为此,您需要更新
web
mobile
,以明确指定类型参数。即使只有一个类型参数的实例化使代码得以编译,scalac也无法理解:

 def web() = {
    implicit val webContext = WebContext("web")
    call[WebContext]("I am calling the method")
 }

 def mobile() = {
    implicit val mobileContext = MobileContext("mobile")
    call[MobileContext]("I am calling the method")
 }
通过将
Context
ContextWriter
组合到一个隐式中,您可能可以使用显式键入。例如,为什么不在实例化
Context
时使用一个ìmplicit
ContextWriter
参数,并完成它呢