从不同类中运行常用函数的最佳方法

HoT*_*icE 2 types functional-programming scala

我有这门课

public abstract class Foo {
    def execute: Unit = ???
}

public abstract class Bar {
    def execute: Unit = ???
}

public class FooFoo extends Foo {
    def execute: Unit = ???
}

public class BarBar extends Bar {
    def execute: Unit = ???
}
Run Code Online (Sandbox Code Playgroud)

在某些我有这种方法的地方:

def executeSomething(body: => AnyRef) : = Try(body) match ...
Run Code Online (Sandbox Code Playgroud)

电话看起来像这样

x match {
  case _: Foo => executeSomething(x.execute)
  case _: Bar => executeSomething(x.execute)
}
Run Code Online (Sandbox Code Playgroud)

是否有某种方式,我可以这样做(没有新的类)

val u = executeSomething(x)
Run Code Online (Sandbox Code Playgroud)

UPD

对不起大家.这个mb实际代码会更清晰

import akka.actor.{Actor, ActorLogging, ActorRef, Props}
import com.google.api.client.auth.oauth2.AuthorizationCodeTokenRequest
import com.google.api.client.googleapis.json.GoogleJsonResponseException
import com.google.api.services.analytics.Analytics
import com.google.api.services.analyticsreporting.v4.AnalyticsReporting
import com.my.lab.messages.{GRequest, GResponse}
import scala.util.{Failure, Success, Try}

class GQueueTask(req: GRequest, ref: ActorRef) extends Actor with ActorLogging {

  def receive: Receive = {
    case _ =>
  }

  def execute(body: => AnyRef): Unit = {
    Try(body) match {
      case Success(r) => ref ! GResponse(req, response = Option(r))
      case Failure(f: GoogleJsonResponseException) =>
            f.printStackTrace()
            ref ! GResponse(req, error = Option(f))
      case _ => ref ! GResponse(req, Option("unknown error"))
    }
  }

  req match {
    case GRequest(request, _) => request match {
      case x: AnalyticsReporting#Reports#BatchGet => execute(x.execute()) // AbstractGoogleClientRequest
      case x: Analytics#Data#Ga#Get => execute(x.execute()) // AbstractGoogleClientRequest
      case x: Analytics#Management#Accounts#List => execute(x.execute()) // AbstractGoogleClientRequest
      case x: Analytics#Management#Webproperties#List => execute(x.execute()) // AbstractGoogleClientRequest
      case x: Analytics#Management#Profiles#List => execute(x.execute()) // AbstractGoogleClientRequest
      case x: AuthorizationCodeTokenRequest => execute(x.execute()) // TokenRequest
      case _ => ref ! GResponse(req)
    }
  }

  context stop self
}
Run Code Online (Sandbox Code Playgroud)

我试图简化"请求匹配"块

Net*_*itz 6

虽然你可以通过使用结构类型(duck typing)来实现它,但是由于scala在运行时使用内省,所以它有很多开销.我认为实现它的最好方法是使用类型类.它在各地的Scala中使用:) Scala的Ordering就是一个例子.

类型类定义与"不相关"类型相关联的功能.您需要做的是以特征的形式定义类型类:

trait Executable[T] {
    def execute(t: T): Unit
}
Run Code Online (Sandbox Code Playgroud)

您需要使您的类型成为该类型类的成员,例如:

implicit object FooFooExecutable extends Executable[FooFoo] {
  override def execute(t: FooFoo): Unit = t.execute()
}
Run Code Online (Sandbox Code Playgroud)

最后一件事是定义将类型类作为参数的方法.

def exec[T: Executable](t: T): Unit = {
  implicitly[ExecTypeClass[T]].execute(t)
}
Run Code Online (Sandbox Code Playgroud)

您可以在此处,此处此处阅读有关类型类的更多信息