2011-07-26 209 views
31

我正在看p。 “Programming in Scala”第二版469页。有一行代码如下:“<:”在Scala中的含义是什么?

type Currency <: AbstractCurrency 

我不能解释这是什么意思。

+5

参见[什么是“特质A <:B”是什么意思?](http://stackoverflow.com/questions/2123663/what-does-trait-a-b-mean) – Jonas

回答

46

它意味着一个抽象类型构件被定义(里面的一些方面,例如一个性状或类),因此,这方面的具体实现必须定义该类型。但是,这种类型(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 
} 
21

这意味着“必须是一个子类型”,“必须符合”,“必须扩展”。 大多数时候,它会显示为一个泛型参数绑定,比如

class Home[P <: Person] 

每个家庭是适合某种类型的人,一个Home[Person]接受任何人,有可能是Home[Student]Home[Elderly],但没有Home[Planet]

type Currency <: AbstractCurrency引入了一个抽象type构件Currency在它出现在class/trait。后裔将不得不选择一种类型,以便他们可以具体。 <:AbstractCurrencies强制他们选择AbstractCurrency的子类型(包括AbstractCurrency,这是允许的)。

抽象型部件是非常接近的类型参数,只是作为一个抽象值构件靠近一个构造符参数。

如果你有class A(val x: X){...},你实例化先用new A(myX)。如果你有class A{val x: X; ...},你可以用新的A{val x = myX } instanciate。

如果你有class Market[Currency <: AbstractCurrency]你实例化与Market[SomeCurrencyType]类型。如果你有Market{type Currency <: AbstractCurrency},你用Market{type Currency = SomeCurrencyType}实例化。但是,Market是有效的类型。这意味着你不知道这个市场使用什么类型的货币(这可能会限制你如何使用它)。

使用一个抽象类型成员而不是一个类型参数可以有优惠,主要是如果类型参数没有出现在该类型的公共接口,如果Market没有Currency出现作为函数参数或结果(不这个例子很可能)。那么客户端不需要写Market[SomeCurrencyType]Market就可以。当然,创建市场时必须知道CurrencyType,但它可以简单地通过Market

3

这个问题是关于Scala的,但我认为这是值得一提的是,<: [?型operatator]是不是唯一的Scala和而不是类型理论起源;例如参见维基百科上关于Subtyping的文章,其广泛使用该操作符。实际上,由于它与类型理论的强大联系,<:不是Scala(优雅地)借用的唯一东西;例如term: Type表示法(见于例如val foo: Foo,def fact(x: Int): Int)也来自Type Theory

0

我想添加一些要点来描述<的可用性好处:表示法。

让我们说,您为您的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实例,都必须传递一个对象作为参数“parameter”,其类/它本身实现了BaseParameter(例如,参数1和参数2)。具体来说,这是一个断言,如果你传递Parameter3,它将不起作用。

相关问题