具有参数化函数的 Scala 动态调度
Scala dynamic dispatch with parameterized function
如何使这段代码起作用?
据我所知,Scala 没有动态调度(类似于 Java)。是否有可能以某种方式模拟动态调度?
或者最好的解决方案是什么?
object Tezt {
case class SuperClazz()
case class SubClazz1() extends SuperClazz
case class SubClazz2() extends SuperClazz
def method(obj: SubClazz1) = {
// stuff
}
def method(obj: SubClazz2) = {
// stuff
}
def func[T <: SuperClazz](obj: T) = {
Tezt.method(obj) // Error: Cannot resolve method reference with such signature
}
}
在单个参数上实现动态分派的标准方法是面向对象的多态性:
abstract class SuperClazz() {
def method(): ReturnType
}
case class SubClazz1() extends SuperClazz {
def method() = {
// stuff
}
}
case class SubClazz2() extends SuperClazz {
def method() = {
// stuff
}
}
// Alternatively just `def func(obj: SuperClazz) =` in this case
def func[T <: SuperClazz](obj: T) =
obj.method()
请注意,您不能将 case class
扩展为另一个 case class
,并且通常认为扩展 case class
是一种糟糕的风格。要实现这一点,您可能需要 method
在 SuperClazz
中是抽象的,因此 SuperClazz
应该是 trait
或 abstract class
.
scala 中动态调度的另一种常见替代方法是模式匹配:
sealed abstract class SuperClazz()
case class SubClazz1() extends SuperClazz
case class SubClazz2() extends SuperClazz
def method(obj: SubClazz1) = {
// stuff
}
def method(obj: SubClazz2) = {
// stuff
}
def func(obj: SuperClazz) =
obj match {
case sc1: SubClazz1 => method(sc1)
case sc2: SubClazz2 => method(sc2)
}
当超级 class 或特征为 sealed
(在本例中为 sealed abstract class SuperClazz()
)时,通常会像这样实现模式匹配。在匹配 sealed super classes 的对象时,编译器会检查你是否列出了匹配中的所有可能性,以确保匹配时不会出现运行时错误。如果你忘记指定一些可能性,编译器会给你一个警告。
模式匹配也适用于多参数动态分配,但与多态性相比,它们通常需要编写更多的样板代码,并且对于线性测试每个匹配案例和调用 unapply
函数可能会有更大的运行时性能成本。
如何使这段代码起作用?
据我所知,Scala 没有动态调度(类似于 Java)。是否有可能以某种方式模拟动态调度?
或者最好的解决方案是什么?
object Tezt {
case class SuperClazz()
case class SubClazz1() extends SuperClazz
case class SubClazz2() extends SuperClazz
def method(obj: SubClazz1) = {
// stuff
}
def method(obj: SubClazz2) = {
// stuff
}
def func[T <: SuperClazz](obj: T) = {
Tezt.method(obj) // Error: Cannot resolve method reference with such signature
}
}
在单个参数上实现动态分派的标准方法是面向对象的多态性:
abstract class SuperClazz() {
def method(): ReturnType
}
case class SubClazz1() extends SuperClazz {
def method() = {
// stuff
}
}
case class SubClazz2() extends SuperClazz {
def method() = {
// stuff
}
}
// Alternatively just `def func(obj: SuperClazz) =` in this case
def func[T <: SuperClazz](obj: T) =
obj.method()
请注意,您不能将 case class
扩展为另一个 case class
,并且通常认为扩展 case class
是一种糟糕的风格。要实现这一点,您可能需要 method
在 SuperClazz
中是抽象的,因此 SuperClazz
应该是 trait
或 abstract class
.
scala 中动态调度的另一种常见替代方法是模式匹配:
sealed abstract class SuperClazz()
case class SubClazz1() extends SuperClazz
case class SubClazz2() extends SuperClazz
def method(obj: SubClazz1) = {
// stuff
}
def method(obj: SubClazz2) = {
// stuff
}
def func(obj: SuperClazz) =
obj match {
case sc1: SubClazz1 => method(sc1)
case sc2: SubClazz2 => method(sc2)
}
当超级 class 或特征为 sealed
(在本例中为 sealed abstract class SuperClazz()
)时,通常会像这样实现模式匹配。在匹配 sealed super classes 的对象时,编译器会检查你是否列出了匹配中的所有可能性,以确保匹配时不会出现运行时错误。如果你忘记指定一些可能性,编译器会给你一个警告。
模式匹配也适用于多参数动态分配,但与多态性相比,它们通常需要编写更多的样板代码,并且对于线性测试每个匹配案例和调用 unapply
函数可能会有更大的运行时性能成本。