scala具有不同属性名称的泛型类型层次结构
我使用加载配置值。例如,对于数据库中的每个表,我存储scala具有不同属性名称的泛型类型层次结构,scala,generics,type-level-computation,pureconfig,Scala,Generics,Type Level Computation,Pureconfig,我使用加载配置值。例如,对于数据库中的每个表,我存储(db:String,table:String)。但是,我需要表示特定的表。因此,每个人都有一个单独的特点。即: trait Thing trait ThingWithStuff extends Thing { def value:String } trait FooThing extends Thing{ def fooThing: ThingWithStuff } trait BarThing extends Thing
(db:String,table:String)
。但是,我需要表示特定的表。因此,每个人都有一个单独的特点。即:
trait Thing
trait ThingWithStuff extends Thing {
def value:String
}
trait FooThing extends Thing{
def fooThing: ThingWithStuff
}
trait BarThing extends Thing{
def barThing: ThingWithStuff
}
它们都具有相同类型的不同属性名称,作为回报,这些属性名称保持不变,即db
和table
。使用某些方法处理这些问题时:
def myMethodFoo(thing:FooThing)= println(thing.fooThing)
def myMethodBar(thing:BarThing)= println(thing.barThing)
这会导致代码重复。尝试使用泛型修复这些问题时,我无法编写如下函数:
def myMethod[T<: Thing] = println(thing.thing)
不能预先具有相同的标识符,否则会覆盖每个值,从而仅保留该标识符最后一项的值。因此,我求助于使用不同的属性名称(table-first,table-second
,或者特别是在示例中:fooThing,barThing
)
如何解决此问题以防止代码重复?下面是一个使用类型类的解决方案,用于
FooThing
和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)
基本上,我们在没有多态性的地方“创建”多态性-两个隐式ThingEx
允许您将fooThing
和barThing
绑定在一起。您只需定义此绑定一次,然后就可以在任何地方使用它
如果特别多态性和类型类对您来说是新的,例如,您可以开始
我希望这有帮助 我想,
FooThing
和BarThing
扩展了东西
?确实应该像这样很棒。有可能自动生成一个封闭特征的抽取器吗?@GeorgHeiler你可以使用Shapeless,或者类似的东西?但我不确定。而且,如果我不仅想读取(提取器),而且还想创建对象,这将如何工作?有动态喷油器吗?@GeorgHeiler这里没有“动态”的东西。所有内容都是静态类型的,因此类型安全。看看不成形的H列表,它们可能就是你想要的。否则,您总是可以在ThingEx
-typeclass上添加另一个函数,类似于def create(thing:ThingWithStuff):FooThing=newfoothing{…thing…}
和def create(thing:ThingWithStuff):BarThing=new BarThingThing{…thing…}
中的,分别地
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!