我在看p。 “Scala编程”第二版469。有一行代码如下:
type Currency <: AbstractCurrency
我无法破译这意味着什么。
答案 0 :(得分:54)
这意味着定义了一个抽象类型成员(在某些上下文中,例如特征或类),因此该上下文的具体实现必须定义该类型。但是,这种类型(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()
}
尝试在没有约束的情况下定义Currency
:
trait RadioactiveBeef
class NiceTry(val curr: RadioactiveBeef) extends Economy {
type Currency = RadioactiveBeef
}
失败。有约束的确定:
trait Euro extends AbstractCurrency
class Angela(val curr: Euro) extends Economy {
type Currency = Euro
}
答案 1 :(得分:30)
这意味着“必须是”的子类型,“必须符合”,“必须延伸”。 大多数情况下,它会显示为泛型参数的绑定,例如
class Home[P <: Person]
每个家庭适合某种类型的人,Home[Person]
接受任何人,可能有Home[Student]
,Home[Elderly]
,但没有Home[Planet]
。
type Currency <: AbstractCurrency
在其显示的type
/ Currency
中引入了一个抽象的class
成员trait
。后代必须选择一种类型才能具体。 &lt ;: AbstractCurrencies强制他们选择AbstractCurrency
的子类型(包括AbstractCurrency
,这是允许的)。
抽象类型成员非常接近类型参数,就像抽象值成员接近构造函数参数一样。
如果您有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
没有{{ 1}}作为函数参数或结果出现(在此示例中不太可能)。然后客户端不需要写Currency
,Market[SomeCurrencyType]
会这样做。当然,在创建市场时必须知道Market
,然后它可以简单地作为CurrencyType
传递。
答案 2 :(得分:5)
我想添加一些点来描述&lt ;: notation的可用性优势。
我们假设您为API定义了以下类:
case class myApiClass[param <: BaseParameter](requestBody: String, parameter: param)
你有一个名为BaseParameter
的特征trait BaseParameter
然后,您有以下参数:
case object Parameter1 extends BaseParameter
case object Parameter2 extends BaseParameter
case object Parameter3
现在,无论何时创建myApiClass实例,都必须传递一个对象作为参数&#34;参数&#34;,其类/本身实现BaseParameter(例如Parameter1和Parameter2)。具体来说,这是一个断言,如果你传递Parameter3就行不了。
答案 3 :(得分:4)
这个问题是关于Scala的,但我认为值得一提的是<:
[类型操作符?]并不是Scala独有的,而是源于类型理论;例如,请参阅维基百科上有关Subtyping的文章,该文章广泛使用了此运算符。
事实上,由于它与类型理论的紧密联系<:
并不是Scala(优雅地)借用它的唯一东西;例如,term: Type
表示法(例如val foo: Foo
,def fact(x: Int): Int
中)也来自Type Theory。