二元操作和参数下界(Binary methods and lower bounds)迄今为止,我们一直将协变性与不可变数据结构联系在一起,然而由于二元操作(Binary methods,就是指一个对象的方法,其参数类型也是这个对象类型,例如:x+y这种——译注)的存在,这种做法并不完全正确。例如,为GenList类增加一个prepend(前追加)方法,最自然的做法是将其定义成为接收一个相应的list元素类型参数:
abstract class GenList[+T] { ...
def prepend(x: T): GenList[T] = // illegal!
new Cons(x, this)
}
可惜这样做会导致类型错误,因为这种定义使得T在GenList中处于逆协变的位置,从而不能标记为协变参数(+T)。这一点非常遗憾,因为从概念上说不可变的list对于其元素类型而言应该是协变的,不过这个问题可以通过参数下界对prepend方法进行泛化而解决:
abstract class GenList[+T] { ...
def prepend[S >: T](x: S): GenList[S] = // OK
new Cons(x, this)
}
这里prepend是一个多态方法,接收T的某个父类型S作为参数,返回元素类型为S的list。这个定义是合法的,因为参数下界被归类为协变位置,从而T在GenList中只出现在协变位置上。
与通配符模式相比较(Comparison with wildcards)Java 5.0中可以提供一种通过通配符标记协变性的方法[45],这种模式本质上是Igarashi和Viroli提出的可变类型参数[26]的一种语法变体。与Scala不同的是,Java 5.0的标注是针对类型表达式而不是类型定义。例如:在每一个需要用到协变的generic list的时候,都将其声明为GenList<? extends T>,这是一个类型表达式,表示其所声明的对象实例的所有元素都是T的子类型。
协变通配符可以用于任何类型表达式当中,但是要注意,出现在非协变的位置上的类型成员将会被忽略(forgotten),这对于保证类型的正确性是必须的。例如:GenCell<? extends Number>类型只有那个get方法(返回Number类型)才有效,而其set方法,由于其类型参数是逆协变的,会被忽略。
在Scala的早期版本中,我们也实验过在调用时标注协变性的方式,类似于通配符。初看之下,这种方式有很大的灵活性,因为一个类型的成员既可以是协变的,也可以是非协变的,用户可以根据情况选择是不是使用通配符。但是,这种灵活性也是有代价的,因为这样作要有用户而不是设计者来保证对协变性的使用是一致的。在实践中我们发现,调用时标注协变性的方式很难保证一致性,经常会出现类型错误。相反,定义时标注协变性对于正确地设计类型有很大帮助,例如可以很好地指导人们设计方法时知道哪些应当使用参数下界。另外,Scala的mixin构成(见第六节)可以让人很容易将一个类分成协变的和非协变的部分,而在Java这种单根结构+接口的继承模型中,这样做是非常麻烦的。因此,Scala的新版本将标注协变性的方式从使用时标注改为了定义时标注。
分享到:
相关推荐
标题中的"IntelliJ的scala插件1.4"指的是IntelliJ IDEA的一个特定版本的Scala插件,即1.4版。这个插件是为那些使用Scala编程语言的开发者提供的,以便在IntelliJ IDEA中获得更好的开发体验。Scala是一种多范式编程...
Scala 概述(瑞士洛桑联邦理工) Scala 概述(瑞士洛桑联邦理工)
标签:apollo-scala-1.3-scaladoc.jar,apollo,scala,1.3,scaladoc,jar包下载,依赖包
标签:apollo-scala-1.4-scaladoc.jar,apollo,scala,1.4,scaladoc,jar包下载,依赖包
**Scala 专题教程 - 抽象成员** 在 Scala 编程语言中,抽象成员是面向对象编程中的一个重要概念,它们允许我们定义一个类或特质,其中包含未实现的方法或字段。这种机制使得我们可以创建规范化的接口,而具体的实现...
**Algebird——Scala的抽象代数库** Algebird是由Twitter开源的一个强大的Scala库,它专注于抽象代数结构和算法。这个库的设计目的是为了帮助处理大规模数据集时的数学运算,尤其在分布式计算环境中。Algebird的...
7. **类型系统**:Scala拥有强大的类型系统,包括类型推断、模式匹配、高阶类型和抽象类型等,这使得编写安全且可维护的代码成为可能。 8. **面向对象编程**:Scala支持传统的类、继承、封装和多态性,同时也引入了...
从上述内容来看,《Programming in Scala.pdf》不仅是一本介绍Scala编程语言的书籍,更是一本为读者提供深入了解和应用Scala语言的实用工具。书籍中的内容覆盖了从基础知识到高级特性的多个层面,确保读者能够在掌握...
scala是一个经典的语言,Scala代表了一个新的语言品种,它抹平了这些人为划分的界限。但是现在scala的相关学习资料不多,因此,本人总结了几篇写的较好的scala学习资料,包含<ScalaQuery_Commerzbank_2011><twitter-...
官方版本,亲测可用
Scala3,也被称为Scala 3或Dotty,是Scala编程语言的一个重大更新,旨在提高其简洁性、可读性和类型安全性。Scala3的发布标志着该语言的进一步成熟,它引入了一系列改进,旨在解决早期版本中的一些痛点,同时保持对...
14. **Scala 与 Java 的五点区别**: - Scala 支持函数式编程,Java 主要是面向对象。 - Scala 有更丰富的类型系统,包括特质和隐式转换。 - Scala 代码通常更简洁,Java 代码可能更冗长。 - Scala 使用 REPL...
Scala支持抽象类和抽象成员,抽象类可以包含抽象方法和抽象字段,用于定义类的公共接口。 #### 继承与覆盖(override) Scala支持继承,子类可以通过覆盖父类的方法来自定义行为。覆盖时需要使用`override`关键字。 ...
Scala概述.pptx 变量.pptx 运算符.pptx 程序流程控制.pptx 函数式编程基础.pptx 面向对象编程(基础部分).pptx 面向对象编程(中级部分).pptx 面向对象编程(高级特性).pptx 隐式转换和隐式参数.pptx 集合(上)-基本使用...
3. 抽象类和特质(Abstract Classes and Traits):Scala中的抽象类和特质可以用来实现多态性和接口定义。抽象类可以有具体方法和抽象方法,而特质更像是轻量级接口,可以多重继承。 4. 适配器模式(Adapter ...
1. Scala概述:了解Scala的历史、目标和设计原则。 2. Scala的下载安装:确保安装了JDK 1.8或更高版本,然后下载Scala安装文件并配置环境变量。 3. IDEA中安装Scala插件:在IntelliJ IDEA中搜索并安装Scala插件,...
官方版本,亲测可用
在大数据编程中,Scala因其高效、类型安全和强大的抽象能力而备受青睐。Spark是使用Scala编写的一个开源大数据处理框架,它提供了高级API,使得开发者可以快速地构建大规模数据处理应用。Spark使用Scala的Actor模型...
Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的概念。这个"scala2.12.1Windows镜像包"是为Windows操作系统设计的Scala编程环境的安装包,版本号为2.12.1。Scala 2.12.x系列是其重要的一个稳定...
1.3 使用Scala 8 1.4 并发 17 1.5 本章回顾与下一章提要 27 第2章 更简洁,更强大 28 2.1 分号 28 2.2 变量声明 29 2.3 Range 31 2.4 偏函数 32 2.5 方法声明 33 2.5.1 方法默认值和...