这将是不合适的。这是为什么,用一个简单的例子。我们不需要两个通用参数,我们不需要亚型TI,TJ和TK要么
trait TA[X <: TA[X]]
trait TC[X <: TA[X]]
class Z extends TC[TA[_]]
类型参数[TA [_]不符合特质TC的类型参数 界[X < :TA [X]]
让我们来看看为什么这个声明是不健全的,它是正确的,它失败了。 让我们添加一些代码。我将TC
更改为class
,以便代码可以转换为java。 A trait
也可以在scala中使用。
trait TA[X <: TA[X]] {def f(x: X) }
class TC[X <: TA[X]] {def g(x: X) = x.f(x)}
它工作正常,x: X
也TA[X]
,所以它有一个例行f
,将接受一个X
。
如果我们试图代替
class TC2[X <: TA[_]] {def g(x: X) = x.f(x)}
那么它失败。我们知道在x
上有一个f
方法,但我们不知道需要什么类型作为参数,我们不知道x
会没事。事实上,假如我们定义
class T1 extends TA[T1]] {def f(t1: T1) = {}; def t1Only = println("only in T1")}
class T2 extends TA[T1]] {def f(t1: T1) = t1.t1Only }
现在,如果TC2
是允许的,我可以创造一个TC2[T2]
,叫g
与T2
,它会叫f
在T2
与T2
。这是不允许的,正确的如T2
没有方法t1Only
。
这显示了为什么TC
不能接受TA[_]]
作为其参数,因为这将允许T2
,这与方法g
不兼容。所以我们为什么不能用参数TA[_]
来定义Z
。这将是完全相同的Java,并与您的原始代码以及。
编辑:我觉得有点内疚,我的答案。由于我给出了为什么不应该被允许的原因,我认为会有一个简单的解决方法。它失败了,我没有时间进一步调查,并张贴没有提及它。解决方法是一种自我类型。如果我们这样做
trait TA[X <: TA[X]] {self: X => }
那么我们就不能定义T2 extends TA[T1]
。所以它原来的代码更有限。但是我们必须接受原始代码的限制,因为它是不健全的。所以它不能只是一个语法技巧,它必须让事情变得不可能,而不是。我认为T2 extends TA[T1]
可能不是有意的东西,而且这是防止的一件事。
显然,它不是,同样的错误。现在我没有一个例子说明它不应该起作用。当然这并不意味着没有。
然后,我看看迈尔的解决方案,想知道为什么T2 extends TA[T1]
的可能性不会伤害它。如此反复,丢弃TB
,Y
,TI
,TJ
和TK
:
trait TA{type X}
trait TC{self => type X <: TA{type X <: self.X}
class Z extends TC{type X = TA}
这编译。而我们能做的
trait T1 extends TA{type X = T1}
trait T2 extends TA{type X = T1}
但是有一件事情我们不能做的:
trait TA {type X <: TA; def f(x: X)}
trait TC {self =>
type X <: TA{type X <: self.X}
def g(x: X) = x.f(x)
}
我们相处g
下面的错误,对于x
参数f
类型不匹配;实测值:x.type(与下面类型TC.this.X)所需 :x.x中
TC
是不完全原酮(如最初,g
被允许)。这是因为TA
上有type X <: self.X
,而TC[X <: TA[X]]
是更强的type X = self.X
。如果我们写出来,我们又回到原来的错误,Z
不编译。所以这个TC
有点在原始的TC
(type X = self.X
)和TC2
(不知道TA的X)之间。再次,对原始代码的限制,我们无法定义g
。
如果限制是可以接受的,你没事。我不知道如何将它写成通用的(也不知道如何用抽象类型成员编写自我类型{self : X =>
)。迈尔斯绝对是专家,我敢肯定,他可以告诉他们做得如何,或者做不到这一点。
虽然我可以跟随你的论点,但我认为你已经通过改变Z的含义解决了问题.Z是一个传统知识,因此在我的例子中是一个TC,但它不是,也不应该是TI。如果TC是一个“经理人”,那么TA就是一个办公室,而TB则是与经理人不在乎的办公室相关的东西,TK是一个会计经理,TI是一个会计办公室,那么Z就是同时又是会计经理和会计部门。另外,我想指出,在我的真实代码中,技术援助和结核病会有所不同,因为他们会定义自己的行为。 –
公平评论:我调整了上面Z的定义来解决它。请注意,您可以添加您想要的任何其他定义,TA,TB,TI,TJ ......您只需要重复类型成员即可。 –