我在看p."Scala编程"第二版469.有一行代码如下:
type Currency <: AbstractCurrency
Run Code Online (Sandbox Code Playgroud)
我无法破译这意味着什么.
0__*_*0__ 58
它意味着定义了一个抽象类型成员(在某些上下文中,例如特征或类),因此该上下文的具体实现必须定义该类型.然而,有一种约束,这种类型的(Currency)必须实际上是一个亚型的AbstractCurrency.这样抽象上下文就可以运行Currency,因为它知道它可以理解每个操作AbstractCurrency.
trait AbstractCurrency {
def disappearInGreece(): Unit
}
abstract class Economy {
type Currency <: AbstractCurrency
def curr: Currency
// can call disappear... because `Currency`
// is an `AbstractCurrency`
def shake(): Unit = curr.disappearInGreece()
}
Run Code Online (Sandbox Code Playgroud)
试图在Currency没有约束的情况下定义:
trait RadioactiveBeef
class NiceTry(val curr: RadioactiveBeef) extends Economy {
type Currency = RadioactiveBeef
}
Run Code Online (Sandbox Code Playgroud)
失败.有约束的确定:
trait Euro extends AbstractCurrency
class Angela(val curr: Euro) extends Economy {
type Currency = Euro
}
Run Code Online (Sandbox Code Playgroud)
Did*_*ont 34
它的意思是"必须是"的子类型,"必须符合","必须延伸".大多数情况下,它会显示为泛型参数的界限,例如
class Home[P <: Person]
Run Code Online (Sandbox Code Playgroud)
每个家庭是适合某种类型的人,一个Home[Person]接受任何人,可能会有Home[Student],Home[Elderly]但没有Home[Planet].
type Currency <: AbstractCurrency在它出现的/ 中引入一个抽象type成员.后代必须选择一种类型才能具体.<:AbstractCurrencies强制他们选择(包括,允许)的子类型.CurrencyclasstraitAbstractCurrencyAbstractCurrency
抽象类型成员非常接近类型参数,就像抽象值成员接近构造函数参数一样.
如果你有class A(val x: X){...},你就可以实现第一个new A(myX).如果你有class A{val x: X; ...},你就会用新的方式实现A{val x = myX }.
如果你有class Market[Currency <: AbstractCurrency]实例的类型Market[SomeCurrencyType].如果你有Market{type Currency <: AbstractCurrency},你实例化Market{type Currency = SomeCurrencyType}.但是,Market是一种有效的类型.这意味着你不知道这个市场使用什么类型的货币(这可能会限制你如何使用它).
使用抽象类型成员而不是类型参数可能有好处,主要是如果类型参数没有出现在类型的公共接口中,如果Market没有Currency出现作为函数参数或结果(在此示例中不太可能).然后客户端不需要写Market[SomeCurrencyType],Market会做.当然,CurrencyType必须在创建市场时知道,但随后可以简单地传递Market.
这个问题是关于 Scala 的,但我认为值得一提的是<:[type operator?] 不是 Scala 独有的,而是起源于类型理论;例如参见有关文章亚型在维基百科上,这使得大量使用该运营商。
事实上,由于它与类型理论的紧密联系<:并不是 Scala(优雅地)从它借来的唯一东西;例如,term: Type符号(见 eg val foo: Foo, def fact(x: Int): Int)也来自Type Theory。
我想添加一些点来描述<:notation的可用性好处.
我们假设您为API定义了以下类:
case class myApiClass[param <: BaseParameter](requestBody: String, parameter: param)
Run Code Online (Sandbox Code Playgroud)
你有一个叫做BaseParameter的特质
trait BaseParameter
Run Code Online (Sandbox Code Playgroud)
然后,您有以下参数:
case object Parameter1 extends BaseParameter
case object Parameter2 extends BaseParameter
case object Parameter3
Run Code Online (Sandbox Code Playgroud)
现在,无论何时创建myApiClass实例,都必须将对象作为参数"参数"传递,其类/本身实现BaseParameter(例如Parameter1和Parameter2).具体来说,这是一个断言,如果传递Parameter3则不起作用.