具有不同属性名称的scala泛型类型层次结构

loading...


0

我使用https://pureconfig.github.io/来加载配置值 . 例如,对于数据库中的每个表,我存储 (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
}

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

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

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

loading...

1回答

  • 1

    这是一个使用 FooThingBarThing 的类型类的解决方案:

    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!
    

    Try it out!

    基本上,我们"create"多态,其中没有任何 - 两个隐式 ThingEx 允许您将 fooThingbarThing 绑定在一起 . 您只需要定义一次此绑定 - 然后您可以在任何地方使用它 .

    如果ad-hoc-polymorphism和类型类对您来说是新的,您可以以here为例 .

    我希望这有帮助!

评论

暂时没有评论!