Scala:限制混合f-有界多态性状的特征

时间:2017-10-09 11:01:59

标签: scala self-type f-bounded-polymorphism

我有:

trait Pet[T <: Pet[T]] {    //disallows: Dog extends Pet[String]
  self: T =>                //disallows: Dog extends Pet[Monkey]
  def rename(s: String): T
  def name: String
}

现在可以轻松添加FelinePet类的特征,如下所示:

trait Feline[T <: Feline[T]] extends Pet[T] {
  self: T =>
  def pur : Unit = println("purrrr")
  def scratch: Unit
}

但是,如果我要在Pet中引入一种类型混合,例如:

trait PetCareInfo[T <: PetCareInfo[T]] {
    self: T with Pet[T] =>
    def registerPet: Unit
  }

我收到错误:

  
    

类型参数[T]不符合特征Pet的类型参数界限[T&lt;:Pet [T]]

  

我的理解是,这是因为PetCareInfo中的自我类型检查会单独查看类型A with B,因此不符合限制。 (不确定这是否是错误或功能)

我可以使用存在类型:

type TypeRestriction: Pet[A] forSome {type A}

trait PetCareInfo[T <: PetCareInfo[T]] {
    self: T with TypeRestriction => //mix-in restriction
    def registerPet: Unit
  }

那会有点工作。两个问题:

  1. 我无法直接在混合限制线中定义存在类型。我明白了:
  2.   
        

    预期但'forSome'找到了。

      

    有没有办法绕过这个?

    1. 在实践中,PetCareInfo的{​​{1}}限制+ forSome自己的限制意味着我不能拥有:

      Pet

    2. 但我想知道是否有办法不依赖于class Cat extends Pet[Dog] with PetCareInfo[Cat]

      更新

      对于问题2,我可以将现有的类型限制更改为:

      Pet

      这似乎解决了这个问题。虽然,仍然无法保证结构type Restriction[T] = A with Pet[A] forSome {type A <: PetCareInfo[T]} trait PetCareInfo[T <: PetCareInfo[T]] { self: Restriction[T] => def registerPet: Unit } 类型与A相同,所以我们仍然依赖于T。 :(

1 个答案:

答案 0 :(得分:2)

试试这个:

Cat

更新:以上演示了的关系。也就是说,Feline PetCareInfo PetCareInfo。这是使Pet成为Cat成员的替代方案,以便PetCareInfo 拥有 Pet。 (我认为这是有道理的。如果这更合适,你可以同等地拥有PetCareInfo // Change of emphasis: T is type of Pet. OK since we're in charge of its definition. trait PetCareInfo[T <: Pet[T]] { // Etc. } trait Pet[T <: Pet[T]] { // Etc. val info: PetCareInfo[T] } abstract class Dog extends Pet[Dog] { // Etc. override val info = new PetCareInfo[Dog] { // Define a what a PetCareInfo looks like for a dog. } } 成员。)

PetCareInfo

如果此类详细信息对代码用户无用,则后一种方法也可用于隐藏info(如果private成员为type arguments [T] do not conform to trait Pet's type parameter bounds [T <: Pet[T]])。

更新2 :BTW,关于错误&#34; trait PetCareInfo[T <: PetCareInfo[T]] { self: T with Pet[T] => // <- Error def registerPet: Unit } &#34;为:

Pet

该消息不言自明:T Pet[T]必须来自T;但是,您只为PetCareInfo定义PetCareInfo[T]PetCareInfo[T]来自Pet[T],而selfPetCareInfo没有明确关系。 T声明仅限制任何具体T实例的类型,不能用于更改PetCareInfo[T]表示的定义。

也就是说,self必须来自T with a Pet[T]T必须属于扩展Pet[T]的对象。但是,由于class CustomButton : UIButton{ @IBInspectable var adjustsTitleFontSizeToFitWidth: Bool = false { didSet { self.titleLabel?.adjustsFontSizeToFitWidth = adjustsTitleFontSizeToFitWidth } } } 不是从{{1}}派生的,因此无法创建此类实例,因此错误。所以,它不是一个错误,而是必不可少的类型检查。