我有两个Java类Foo
和Bar
(来自我不应该更改的第三部分库)并且它们与任何interface
,{{1}无关或任何其他类。
但是他们有签名方法,如
abstract
在两个类中都是相同的,另一个方法与列表中返回的对象类型非常相似:
为班级public String createToken(String id)
=> Foo
并为班级public List[FooItem] getItems(String id)
=> Bar
在我的Scala代码中,我在基本上重复的方法中使用这两个类。例如:
public List[BarItem] getItems(String id)
正如您所看到的,代码几乎相同,但对于许多方法(而不仅仅是两个类),它变成了一种巨大的重复代码。
是否有任何方法可以使用Scala来概括代码以获得某种:
def getFooItems(foo: Foo, id: String): Vector[FooItem] = {
foo.createToken(id)
foo.getItems(id).asScala.toVector
}
def getBarItems(bar:Bar, id: String): Vector[BarItem] = {
bar.createToken(id)
bar.getItems(id).asScala.toVector
}
或鸭子打字唯一的方式?
答案 0 :(得分:3)
我建议你试试typeclass pattern。
首先,您必须定义Foo
和Bar
的公共接口:
trait Tokenable[T, TItem] {
def createToken(t: T, id: String): String
def getItems(t: T, id: String): List[TItem]
}
然后,您需要为要应用它的每个类定义实现:
object FooBar {
class Foo {
def createToken(id: String): String = ???
def getItems(id: String): List[FooItem] = ???
}
class Bar {
def createToken(id: String): String = ???
def getItems(id: String): List[BarItem] = ???
}
class FooItem
class BarItem
implicit object FooTokenable extends Tokenable[Foo, FooItem] {
def createToken(f: Foo, id: String) = f.createToken(id)
def getItems(f: Foo, id: String) = f.getItems(id)
}
implicit object BarTokenable extends Tokenable[Bar, BarItem] {
def createToken(b: Bar, id: String) = b.createToken(id)
def getItems(b: Bar, id: String) = b.getItems(id)
}
}
现在,您可以在具有隐式Tokenable
参数的任何方法中使用它:
import FooBar._
def getItemsAsVector[T, TItem](t: T, id: String)
(implicit tok: Tokenable[T, TItem]) = {
tok.createToken(t, id)
tok.getItems(t, id).toVector
}
val vector = getItemsAsVector(new Foo, "my_id")