【问题标题】:Family Polymorphism + Mixins?家族多态性 + Mixins?
【发布时间】:2013-02-05 09:03:51
【问题描述】:

我有一系列类型,我想使用 mixins 模块化地“丰富”它们。例如:

trait Family {
  self =>
  trait Dog {
    def dogname:String
    def owner:self.Person
  }
  trait Person {
    def name:String
    def pet:self.Dog
  }
}

trait SerializableFamily extends Family {
  trait Dog extends super.Dog {
    def toSimpleString:String = "Dog(" + dogname + ")"
  }
  trait Person extends super.Person {
    def toSimpleString:String = "Person(" + name + ") and his pet " + pet.toSimpleString
  }
}

trait SerializableFamily2 extends Family {
  trait Dog extends super.Dog {
    def toLoudString:String = "Dog(" + dogname.toUpperCase + ")"
  }
  trait Person extends super.Person {
    def toLoudString:String = "Person(" + name.toUpperCase + ") and his pet " + pet.toLoudString
  }
}

但是,上述方法不起作用(Scala 2.9.1)。最后一个表达式编译失败(pet.toSimpleString)。

这只是我从我尝试过的几个策略中挑选出来的一个随机策略:自键入、抽象类型、超级 [...] 等。

我希望最终能够做这样的事情:

val family = new Family with SerializableFamily with TraversableFamily with FooFamily {}

其中每个 mixin 都会为家族中的一个或多个类型添加一组协作方法。

这是我见过的一种常见模式,通过使用隐式包装器、基于模式匹配的访问者等来解决。但由于它只是常规 mixin 模式的递归应用,我想知道是否有更简单的方法来实现它。

【问题讨论】:

    标签: scala mixins traits


    【解决方案1】:

    您的情况会出现错误,因为 mixins 中的 DogPerson 不会覆盖 Family 中的 DogPerson,因此 self.Person 仍然指的是Family.Person

    这可能更接近你想要的

    trait Family {
      // type DogType = Dog won't work because then two different mixins 
      // have incompatible DogType implementations
      type DogType <: Dog
      type PersonType <: Person
    
      trait Dog {
        def dogname:String
        def owner:PersonType 
      }
      trait Person {
        def name:String
        def pet:DogType 
      }
    }
    
    trait SerializableFamily extends Family {
      type DogType <: Dog
      type PersonType <: Person
    
      trait Dog extends super.Dog {
        def toSimpleString:String = "Dog(" + dogname + ")"
      }
      trait Person extends super.Person {
        def toSimpleString:String = "Person(" + name + ") and his pet " + pet.toSimpleString
      }
    }
    

    但是你有一些令人讨厌的东西

    new Family with SerializableFamily with TraversableFamily with FooFamily {
      type DogType = super[SerializableFamily].Dog with super[TraversableFamily].Dog with super[FooFamily].Dog
    }
    

    【讨论】:

    • 这主要是我想出的,但如果我理解正确的话,这并不是 OP 真正想要的。他希望DogPerson 的所有版本在混音时叠加,我认为这根本不可能。
    • 为此+1,因为这可能是您可以获得的最接近的。但是明确混合所有版本的特征非常冗长:(
    猜你喜欢
    • 1970-01-01
    • 2020-05-31
    • 1970-01-01
    • 1970-01-01
    • 2018-03-05
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多