"<:" 在 Scala 中是什么意思?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6828875/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What does "<:" mean in Scala?
提问by deltanovember
I'm looking at p. 469 of "Programming in Scala" Second Edition. There is a line of code that reads:
我在看 p。“Scala 编程”第二版的 469。有一行代码是这样写的:
type Currency <: AbstractCurrency
I cannot decipher what this means.
我无法解读这意味着什么。
回答by 0__
It means an abstract type member is defined (inside some context, e.g. a trait or class), so that concrete implementations of that context must define that type. However, there is a constraint that this type (Currency) must actually be a subtypeof AbstractCurrency. That way the abstract context can operate with Currency, knowing that it understands every operation of AbstractCurrency.
这意味着定义了一个抽象类型成员(在某些上下文中,例如特征或类),因此该上下文的具体实现必须定义该类型。然而,有一种约束,这种类型的(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()
}
Trying to define Currencywithout constraints:
尝试Currency无约束地定义:
trait RadioactiveBeef
class NiceTry(val curr: RadioactiveBeef) extends Economy {
type Currency = RadioactiveBeef
}
Fails. With constraints ok:
失败。有约束条件:
trait Euro extends AbstractCurrency
class Angela(val curr: Euro) extends Economy {
type Currency = Euro
}
回答by Didier Dupont
It means "must be a subtype of", "must conforms to", "must extends". Most of the time, it would appear as a bound on a generic parameter, such as
它的意思是“必须是”的子类型,“必须符合”,“必须扩展”。大多数情况下,它会显示为泛型参数的边界,例如
class Home[P <: Person]
Each Home is fit for a certain type of person, a Home[Person]accepts any person, there might be Home[Student], Home[Elderly], but no Home[Planet].
每个家庭都适合某种类型的人,aHome[Person]接受任何人,可能有Home[Student], Home[Elderly],但没有Home[Planet]。
type Currency <: AbstractCurrencyintroduces an abstract typemember Currencyin the class/traitwhere it appears. Descendants will have to choose a type so that they can be concrete. The <: AbstractCurrencies force them to choose a subtype of AbstractCurrency(including AbstractCurrency, which is allowed).
type Currency <: AbstractCurrency在/出现的地方引入一个抽象type成员。后代将不得不选择一种类型,以便他们可以是具体的。<: AbstractCurrencies 强制他们选择子类型(包括,这是允许的)。CurrencyclasstraitAbstractCurrencyAbstractCurrency
An abstract type member is very close to a type parameter, just as an abstract value member is close to a constructor parameter.
抽象类型成员非常接近类型参数,就像抽象值成员接近构造函数参数一样。
If you have class A(val x: X){...}, you instanciate the first with new A(myX). If you have class A{val x: X; ...}, you instanciate with new A{val x = myX }.
如果你有class A(val x: X){...},你用 .instanciate 第一个new A(myX)。如果有class A{val x: X; ...},则使用 new 实例化A{val x = myX }。
If you have class Market[Currency <: AbstractCurrency]you instanciate the type with Market[SomeCurrencyType]. If you have Market{type Currency <: AbstractCurrency}, you instantiate with Market{type Currency = SomeCurrencyType}. However, Marketis a valid type. It means you don't know what type of currency this market uses (which may restrict how you can use it).
如果你有class Market[Currency <: AbstractCurrency]你实例化的类型Market[SomeCurrencyType]。如果有Market{type Currency <: AbstractCurrency},则用 实例化Market{type Currency = SomeCurrencyType}。但是,Market是有效的类型。这意味着你不知道这个市场使用什么类型的货币(这可能会限制你如何使用它)。
Using an abstract type memberrather than a type parameter may have benefits, mostly if the type parameter does not appear in the public interface of the type, if Markethas no Currencyappearing as a function parameter or result (not too likely on this example). Then client does not need to write Market[SomeCurrencyType], Marketwill do. Of course, the CurrencyTypewill have to be known when a market is created, but then it may be passed along simply as Market.
使用抽象类型成员而不是类型参数可能有好处,主要是如果类型参数没有出现在类型的公共接口中,如果Market没有Currency作为函数参数或结果出现(在这个例子中不太可能)。那么客户端不需要写Market[SomeCurrencyType],Market就可以了。当然,CurrencyType必须在创建市场时知道 ,但随后它可以简单地作为 传递Market。
回答by Arijit
I want to add some points which will describe the usability benefits of the <: notation.
我想添加一些要点来描述 <: 符号的可用性优势。
Let us say, you define the following class for your API:
假设您为 API 定义了以下类:
case class myApiClass[param <: BaseParameter](requestBody: String, parameter: param)
You have a trait called BaseParameter
你有一个叫做 BaseParameter 的特征
trait BaseParameter
Then, you have the following parameters:
然后,您有以下参数:
case object Parameter1 extends BaseParameter
case object Parameter2 extends BaseParameter
case object Parameter3
Now, whenever you create a myApiClass instance, you must pass an object as the argument "parameter", whose class/which itself implements BaseParameter (e.g. Parameter1 and Parameter2). Concretely, this is an assertion, and would not work if you pass Parameter3.
现在,无论何时创建 myApiClass 实例,都必须传递一个对象作为参数“参数”,其类/它本身实现了 BaseParameter(例如 Parameter1 和 Parameter2)。具体来说,这是一个断言,如果您传递 Parameter3,它将不起作用。
回答by Erik Kaplun
This question is about Scala but I think it's worth mentioning that the <:[type operatator?] is not unique to Scala and instead originates in Type Theory; see for example the article about Subtypingon Wikipedia which makes extensive use of this operator.
这个问题是关于 Scala 的,但我认为值得一提的是<:[type operator?] 不是 Scala 独有的,而是起源于类型理论;例如,参见维基百科上关于Subtyping的文章,它广泛使用了这个运算符。
In fact, due to its strong connections with type theory <:is not the only thing Scala (elegantly) borrowed from it; for example the term: Typenotation (seen in e.g. val foo: Foo, def fact(x: Int): Int) also comes from Type Theory.
事实上,由于它与类型理论的紧密联系<:并不是 Scala(优雅地)从它那里借来的唯一东西;例如,term: Type符号(见 eg val foo: Foo, def fact(x: Int): Int)也来自Type Theory。

