What does "<:" mean in Scala?
I'm looking at p. 469 of "Programming in Scala" Second Edition. There is a line of code that reads:
开发者_如何学Pythontype Currency <: AbstractCurrency
I cannot decipher what this means.
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 subtype of AbstractCurrency
. That way the abstract context can operate with Currency
, knowing that it understands every operation of 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 Currency
without constraints:
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
}
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]
.
type Currency <: AbstractCurrency
introduces an abstract type
member Currency
in the class
/trait
where 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).
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 }
.
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, Market
is a valid type. It means you don't know what type of currency this market uses (which may restrict how you can use it).
Using an abstract type member rather than a type parameter may have benefits, mostly if the type parameter does not appear in the public interface of the type, if Market
has no Currency
appearing as a function parameter or result (not too likely on this example). Then client does not need to write Market[SomeCurrencyType]
, Market
will do. Of course, the CurrencyType
will have to be known when a market is created, but then it may be passed along simply as Market
.
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:
case class myApiClass[param <: BaseParameter](requestBody: String, parameter: param)
You have a trait called 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.
This question is about Scala but I think it's worth mentioning that the <:
[type operator?] is not unique to Scala and instead originates in Type Theory; see for example the article about Subtyping on Wikipedia which makes extensive use of this operator.
In fact, due to its strong connections with type theory <:
is not the only thing Scala (elegantly) borrowed from it; for example the term: Type
notation (seen in e.g. val foo: Foo
, def fact(x: Int): Int
) also comes from Type Theory.
精彩评论