0

我使用https://pureconfig.github.io/来加载配置值。例如,对于数据库中的每个表,我存储(db: String, table: String). 但是,我需要表示特定的表。因此,每个人都有不同的特质。IE:

trait Thing
trait ThingWithStuff extends Thing {
    def value:String
}

trait FooThing extends Thing{
    def fooThing: ThingWithStuff
}

trait BarThing extends Thing{
    def barThing: ThingWithStuff
}

它们都有一个不同的属性名称,具有相同的类型,作为回报,它们拥有 iedbtable. 使用某些方法处理这些时:

def myMethodFoo(thing:FooThing)= println(thing.fooThing)
def myMethodBar(thing:BarThing)= println(thing.barThing)

它会导致代码重复。尝试使用泛型解决这些问题,我无法编写如下函数:

def myMethod[T<: Thing] = println(thing.thing)

因为属性名称会不同。有没有聪明的方法?笔记:

table-first {
db = "a"
table = "b"
}
table-second {
db = "foo"
table = "baz"
}

前面不能有相同的标识符,否则它将覆盖每个值以仅保存此标识符的最后一项的值。因此,我求助于使用不同的属性名称(table-first, table-second或专门用于示例fooThing, barThing:)

如何解决此问题以防止代码重复?

4

1 回答 1

1

这是使用类型类的解决方案FooThingand BarThing

trait Thing

trait ThingWithStuff {
    def value: String
}

trait FooThing extends Thing {
    def fooThing: ThingWithStuff
}

trait BarThing extends Thing {
    def barThing: ThingWithStuff
}

// Define implicits:

trait ThingEx[SomeThing <: Thing] {
  def extract(thing: SomeThing): ThingWithStuff
}

implicit val fooThingEx = new ThingEx[FooThing]{
  def extract(thing: FooThing): ThingWithStuff = thing.fooThing
}

implicit val barThingEx = new ThingEx[BarThing]{
  def extract(thing: BarThing): ThingWithStuff = thing.barThing
}

// Define the method:

def myMethod[SomeThing <: Thing](thing: SomeThing)(implicit thingEx: ThingEx[SomeThing]) =
  println(thingEx.extract(thing).value)

// Try it out:

val foo = new FooThing {
  def fooThing = new ThingWithStuff {
    def value = "I am a FooThing!"
  }
}


val bar = new BarThing {
  def barThing = new ThingWithStuff {
    def value = "I am a BarThing!"
  }
}

myMethod(foo)

myMethod(bar)

结果:

I am a FooThing!
I am a BarThing!

试试看!

基本上,我们在没有多态的地方“创建”了多态——这两个隐式ThingEx允许你绑定fooThingbarThing在一起。您只需定义一次绑定 - 然后您可以在任何地方使用它。

如果ad-hoc-polymorphism类型类对您来说是新的,例如,您可以从这里开始。

我希望这有帮助!

于 2018-12-10T13:33:24.173 回答