[英]Run function with generic parameter without using asInstanceOf
here is my sample scala code: 这是我的示例scala代码:
object App {
abstract class BaseAction
type ApiAction[T <: BaseAction] = (T) => Unit
case class FirstAction(name: String) extends BaseAction
case class SecondAction(surname: String) extends BaseAction
def action1[Z <: BaseAction] = {
(a: Z) => { // Here i'would like to have a: FirstAction
val z = a.asInstanceOf[FirstAction]
println("Running action: " + z.name )
}
}
def action2[Z <: BaseAction] = {
(a: Z) => { // Here i'would like to have a: SecondAction
val z = a.asInstanceOf[SecondAction]
println("Running action " + z.surname )
}
}
def myActions[T <: BaseAction] = Map[String, ApiAction[T]]("a1" -> action1[T], "a2" -> action2[T])
myActions("a1")(FirstAction("Action 1"))
myActions("a2")(SecondAction("Action 2"))
}
I have few action functions, which does different things. 我有很少的动作功能,它们做了不同的事情。 Each action function receive one parameter: action class, where all action classes inherits from BaseAction abstract class.
每个动作函数都接收一个参数:action class,其中所有动作类都继承自BaseAction抽象类。
Function myActions is Map of actionName to action function. 函数myActions是actionName到action函数的Map。
My code is working, but i think that using asInstanceOf is not good practice, and i want to know how can i write this code only using generic types, without asInstanceOf. 我的代码正在运行,但我认为使用asInstanceOf并不是一个好习惯,我想知道如何只使用泛型类型编写此代码,而不使用asInstanceOf。
The thing is that you are doing a lot of "you should not do this stuff". 问题是你做了很多“你不应该做这些事情”。
I will try to give you are "better" ( as per most scala people) way for writing the same thing. 我将尝试给你“更好”(按照大多数scala人)的方式来写同样的东西。 The changes include the use of information from type-bounds and that custom type
ApiAction
to write a more predictable and organised code. 这些更改包括使用来自类型边界的信息以及自定义类型
ApiAction
来编写更可预测和有组织的代码。
First you have following abstractions, 首先你有以下抽象,
abstract class BaseAction
type ApiAction[T <: BaseAction] = (T) => Unit
case class FirstAction(name: String) extends BaseAction
case class SecondAction(surname: String) extends BaseAction
Now you can use these abstractions to write your Actions
object, 现在您可以使用这些抽象来编写您的
Actions
对象,
object MyActions {
val action1: ApiAction[FirstAction] = {
case FirstAction(name) => println("Running action :: " + name)
}
val action1Other: ApiAction[FirstAction] = (fa: FirstAction) => {
println("Running action :: " + fa.name)
}
val action2: ApiAction[SecondAction] = {
case SecondAction(surname) => println("Running action :: " + surname)
}
val action2Other: ApiAction[SecondAction] = (sa: SecondAction) => {
println("Running action :: " + sa.surname)
}
// but lets say you wanted a generic ApiAction
val actionGeneric: ApiAction[BaseAction] = {
case FirstAction(name) => println("Running action :: " + name)
case SecondAction(surname) => println("Running action :: " + surname)
}
}
Now you can use these "actions" as you want in your app, 现在,您可以在应用中使用这些“操作”,
object MyApp extends App {
MyActions.action1(FirstAction("Action 1"))
MyActions.action1Other(FirstAction("Action 1 Other"))
MyActions.actionGeneric(FirstAction("Action 1 Generic"))
MyActions.action2(SecondAction("Action 2"))
MyActions.action2Other(SecondAction("Action 2 Other"))
MyActions.actionGeneric(SecondAction("Action 2 Generic"))
}
You can use idiomatic Scala pattern matching instead of asInstanceOf
: 您可以使用惯用的Scala模式匹配而不是
asInstanceOf
:
val z = a match {
case FirstAction(name) => println("Running action " + name)
case _ => println("Error")
}
Note that pattern matching still uses isInstanceof
+ asInstanceOf
under the hood, but it's considered good practice, unlike calling asInstanceOf
directly. 请注意,模式匹配仍然使用
isInstanceof
+ asInstanceOf
,但它被认为是一种很好的做法,不像直接调用asInstanceOf
。
By the way, it would probably be wise to organize your code a bit differently so that you match only once, instead of having two separate "first action or error" and "second action or error" blocks: 顺便说一下,组织你的代码可能是明智的,这样你只匹配一次,而不是有两个单独的“第一个动作或错误”和“第二个动作或错误”块:
def action[Z <: BaseAction] = {
(a: Z) => a match {
case FirstAction(name) => println("Running action " + name)
case SecondAction(surname) => println("Running action " + surname)
case _ => println("Error")
}
}
def myActions[T <: BaseAction] = Map[String, ApiAction[T]]("a1" -> action[T], "a2" -> action[T])
myActions("a1")(FirstAction("Action 1"))
myActions("a2")(SecondAction("Action 2"))
// output:
// Running action Action 1
// Running action Action 2
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.