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)
我试图简化"请求匹配"块
虽然你可以通过使用结构类型(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)