Abstract types, such as traits and abstract classes, can in turn have abstract type members. This means that the concrete implementations define the actual types. Here’s an example:
trait Buffer { type T val element: T }
trait Buffer: type T val element: T
Here we have defined an abstract type T. It is used to describe the type of element. We can extend this trait in an abstract class, adding an upper-type-bound to T to make it more specific.
abstract class SeqBuffer extends Buffer { type U type T <: Seq[U] def length = element.length }
abstract class SeqBuffer extends Buffer: type U type T <: Seq[U] def length = element.length
Notice how we can use yet another abstract type U in the specification of an upper-type-bound for T. This class SeqBuffer allows us to store only sequences in the buffer by stating that type T has to be a subtype of Seq[U] for a new abstract type U.
Traits or classes with abstract type members are often used in combination with anonymous class instantiations. To illustrate this, we now look at a program which deals with a sequence buffer that refers to a list of integers:
abstract class IntSeqBuffer extends SeqBuffer { type U = Int } def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer = new IntSeqBuffer { type T = List[U] val element = List(elem1, elem2) } val buf = newIntSeqBuf(7, 8) println("length = " + buf.length) println("content = " + buf.element)
abstract class IntSeqBuffer extends SeqBuffer: type U = Int def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer = new IntSeqBuffer: type T = List[U] val element = List(elem1, elem2) val buf = newIntSeqBuf(7, 8) println("length = " + buf.length) println("content = " + buf.element)
Here the factory newIntSeqBuf uses an anonymous class implementation of IntSeqBuffer (i.e. new IntSeqBuffer) to set the abstract type T to the concrete type List[Int].
It is also possible to turn abstract type members into type parameters of classes and vice versa. Here is a version of the code above which only uses type parameters:
abstract class Buffer[+T] { val element: T } abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] { def length = element.length } def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] = new SeqBuffer[Int, List[Int]] { val element = List(e1, e2) } val buf = newIntSeqBuf(7, 8) println("length = " + buf.length) println("content = " + buf.element)
abstract class Buffer[+T]: val element: T abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T]: def length = element.length def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] = new SeqBuffer[Int, List[Int]]: val element = List(e1, e2) val buf = newIntSeqBuf(7, 8) println("length = " + buf.length) println("content = " + buf.element)
Note that we have to use variance annotations here (+T <: Seq[U]) in order to hide the concrete sequence implementation type of the object returned from method newIntSeqBuf. Furthermore, there are cases where it is not possible to replace abstract type members with type parameters.
相关知识
Members Mark 宁波芝麻汤圆热量
type
input type=submit
Diabetes Mellitus (Type 1 and Type 2) Causes, Risk Factors, Symptoms
综述与专论:丙氨酰
宜享健康 Members Mark 宜享健康 NFC椰子汁冷藏2瓶 54元
区别script中的type=”text/javascript”和language=”Javascript”
我的世界type=item,r=!100什么意思?
老年慢性病患者健康信息寻求行为现状及影响因素路径分析
The Mental Well
网址: Abstract Type Members https://m.trfsz.com/newsview1676140.html