我有:
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
}
现在可以轻松添加Feline
等Pet
类的特征,如下所示:
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
}
那会有点工作。两个问题:
预期但'forSome'找到了。
有没有办法绕过这个?
在实践中,PetCareInfo
的{{1}}限制+ forSome
自己的限制意味着我不能拥有:
Pet
但我想知道是否有办法不依赖于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
。 :(
答案 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]
,而self
与PetCareInfo
没有明确关系。 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}}派生的,因此无法创建此类实例,因此错误。所以,它不是一个错误,而是必不可少的类型检查。