最好的方法,从不同类别
我有这个类最好的方法,从不同类别
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 = ???
}
在某些运行常用的功能,我有这样的方法:
def executeSomething(body: => AnyRef) : = Try(body) match ...
而且调用这个样子
x match {
case _: Foo => executeSomething(x.execute)
case _: Bar => executeSomething(x.execute)
}
有没有什么方法可以做到这一点(没有新班级)
val u = executeSomething(x)
?
UPD
对不起,伙计们。这个m.b.真正的代码会更加清晰
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
}
我试图简化 “的要求匹配” 块
虽然可以使用结构类型(鸭打字)实现它,它因为在运行时使用阶内省很大的开销。我认为实现它的最好方法是使用类型类。 Scala的Ordering就是一个例子。
A型类定义与“无关”类型相关联的功能。 你需要做的是在一个特点的形式定义类型类:
trait Executable[T] {
def execute(t: T): Unit
}
比你需要让你的类型的类型类的成员,例如:
implicit object FooFooExecutable extends Executable[FooFoo] {
override def execute(t: FooFoo): Unit = t.execute()
}
而且最后一件事是定义将您的类型类作为参数的方法。
def exec[T: Executable](t: T): Unit = {
implicitly[ExecTypeClass[T]].execute(t)
}
我想这和它的工作:
object Dummy {
abstract class Foo {
def execute: Unit
}
abstract class Bar {
def execute: Unit
}
class FooFoo extends Foo {
def execute: Unit = { println("Foo") }
}
class BarBar extends Bar {
def execute: Unit = { println("Bar") }
}
def run(x: AnyRef): Unit = {
x match {
case f: Foo => f.execute
case b: Bar => b.execute
case _ =>
}
}
def main(args: Array[String]): Unit = {
val any = new BarBar()
run(any)
}
}
它印刷
Bar
这看起来像duck-typing
的一个很好的用例。
Duck Typing
更正式地称为Structural Types
。
A Duck Type
可以被认为只是所需的一组属性的specification
。 Compile time reflection
用于确保提供的参数的type
与您的duck-type
的specification
兼容。所以它为您提供编译时类型安全性。
然后它使用run time reflection
实际调用提供的实例上的各个方法。
所以,
比方说你有以下的抽象,
abstract class Foo {
def execute(): Unit
}
abstract class Bar {
def execute(): Unit
}
class FooFoo extends Foo {
override def execute(): Unit = {
println("FooFoo")
}
}
class BarBar extends Bar {
override def execute(): Unit = {
println("BarBar")
}
}
注::我已经加入()
到所有Unit
方法。这是Scala中的一个惯例,所有带副作用的方法应该有()
。除了副作用之外,Unit
方法不能做任何事情。
现在...你只需要定义一个duck-type
的共享行为,
type HasExecuteMethod = {
def execute(): Unit
}
现在...让定义一个使用这种鸭式功能,
def doExecute(hasExecuteMethod: HasExecuteMethod): Unit = {
hasExecuteMethod.execute()
}
而且...在这里你有它。这个doExecute
方法将接受任何具有def execute(): Unit
成员的类的实例。
你用什么语言?斯卡拉没有'公共class',它需要'override'修饰符'FooFoo','BarBar',以及最重要的,招用'type'不起作用。 – dveim
我实际上认为,因为OP公顷问这样一个很好的问题,提供的代码不会有这样明显的错误,比如' public'。而你其实并不“需要”来指定'override'。你这样做,作为一个很好的做法,以防止出错。 –
@dveim它现在所有的工作。我没有忘记键入'='。它应该已经'输入HasExecuteMethod = {'。并且作为f或公共事物......我从OP的问题中复制粘贴,我没有注意到这些显而易见的问题。 –
为什么不能延伸功能,只是调用'VAL U = X()'?用'apply'代替'execute'。 – Bergi
我有一些遗留代码看起来像这样。我只能修改executeSomething及以下:( – HoTicE
码你就不能使用重载executeSomething'高清executeSomething(X:美孚)= x.execute; 高清executeSomething(X:酒吧)?= x.execute' –