博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
dotty编译器语法特性之一交叉类型,联合类型和文本单例类型
阅读量:6718 次
发布时间:2019-06-25

本文共 2281 字,大约阅读时间需要 7 分钟。

hot3.png

###翻译: #交叉类型

trait Resettable {  def reset(): this.type}trait Growable[T] {  def add(x: T): this.type}def f(x: Resettable & Growable[String]) = {  x.reset()  x.add("first")}

这里x要求必须是Resettable类型和Growable[T]类型,交叉类型A & B 替代了scala2中的复合类型A with B(目前,这种复合类型仍然可以使用,但是未来会被废除)

with 复合类型不同,& 交叉类型是可互换的,比如:A & BB & A是相同的类型。 一个交叉类型A & B的所有成员,是类型A的所有成员和类型B的所有成员之和。

例如Resettable & Growable[String]类型拥有resetadd两个分别来自两个类型的成员方法。

如果一个成员既出现在A类型中,又出现在B类型中,那么这个成员的类型在类型A & B中表现为A类型和B类型交叉。比如下面的例子:

trait A {  def children: List[A]  def say:Int = 1}trait B {  def children: List[B]  def say:String = "2"}class C extends A with B {  def children: List[A & B] =  List(new C)  override  def say:Int & String = super.say  + 3 }val x: A & B = new Cval xs: List[A] & List[B] = x.childrenval ys: List[A & B] = x.children

这个成员childrenA & B的类型,是 childrenA中的类型List[A]childrenB中类型List[B]的交叉类型List[A] & List[B] 。这个能进一步简化为List[A & B] ,因为List是协变的。

联合类型

翻译:

操作符|创建一个联合类型

case class UserName(name: String) {  def lookup(admin: Admin): UserData}case class Password(hash: Hash) {  def lookup(admin: Admin): UserData}def help(id: UserName | PassWord) = {  val user = id match {    case UserName(name) => lookupName(name)    case Password(hash) => lookupPassword(hash)  }  // ...}

联合类型是双重交叉类型。联合类型A|B的值是所有A的值和所有B的值之和。 | 联合类型是可互换的,比如:A | BB | A是相同的类型。

只有当一个表达式明确给出类型的时候,编译器才会给这个表达式赋值一个联合类型,例如:

scala> val password = Password(123)val password: Password = Password(123)scala> val name = UserName("Eve")val name: UserName = UserName(Eve)scala> if (true) name else passwordval res2: Object & Product = UserName(Eve)scala> val either: Password | UserName = if (true) name else passwordval either: Password | UserName = UserName(Eve)scala>help(either)

res2的类型是Object & Product,它是 UserNameProduct的一个超类,但不是类型的最小超类Password | UserName。如果想获得最小超类,必须明确给出类型定义,就像这里的val either: Password | UserName的类型。要调用联合类型的成员,使用类型匹配match,比如这里的help方法

#文本单例类型 看以下例子:

object Literals{  val fortyTwo: 42 = 42  val `2`: 2 = 2  val fortyFour: 44 = fortyTwo + `2`  val text: "text" = "text"  def id[T](a: T) = a  val two: 2 = id(`2`) final val T = 1val x: T.type = 2    // error , 2 should be 1}

这里 val x: T.type = 2 会报错,因为T.type文本类型只能赋值为原本定义的值,这里是1。这里的final val定义个值不可变的单例文本类型,使用T.type来引用,且只能赋值为原值。

转载于:https://my.oschina.net/jackywyz/blog/913099

你可能感兴趣的文章
【原+转】用CMake代替makefile进行跨平台交叉编译
查看>>
swift3.0:CoreData的使用
查看>>
Silverlight实用窍门系列:3.Silverlight鼠标动态绘制矩形【实例源码下载】
查看>>
postmaster.c 中的 ListenAddresses
查看>>
托付和事件的使用
查看>>
关于Java的转义字符
查看>>
测试管理工具QC使用指南--QC用户
查看>>
使用FDO API连接到各种数据源
查看>>
CentOS 6.5下Redis安装记录
查看>>
Activiti-5.3工作流引擎-源码解析(流程文档解析)
查看>>
python3中的迭代器与生成器
查看>>
开源Flex Air版免费激情美女视频聊天室,免费网络远程视频会议系统((Flex,Fms3联合打造))...
查看>>
在虚拟机中搭建SQLITE环境,并测试其是否安装成
查看>>
jsp页面传递参数是如何与javabean进行关联的
查看>>
Sql Server的弱口令入侵测试以及防范
查看>>
IE浏览器开启对JavaScript脚本的支持
查看>>
PHP 魔术方法__set() __get() 方法
查看>>
linux下切割catalina.out文件,按天生成文件
查看>>
macOS 下的 Eclipse.ini 文件在哪?
查看>>
UVA - 10785 The Mad Numerologist
查看>>