Scala:如何围绕不相关的Java类来概括行为

时间:2016-12-11 10:15:17

标签: java scala

我有两个Java类FooBar(来自我不应该更改的第三部分库)并且它们与任何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
}

或鸭子打字唯一的方式?

1 个答案:

答案 0 :(得分:3)

我建议你试试typeclass pattern

首先,您必须定义FooBar的公共接口:

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")