为了账号安全,请及时绑定邮箱和手机立即绑定

Scala中的类型归属的目的是什么?

Scala中的类型归属的目的是什么?

蝴蝶刀刀 2019-11-27 10:05:30
规范中关于类型归属的信息不多,而且关于目的的用途当然也没有。除了“使传递的varargs起作用”之外,我还要使用类型归属吗?以下是一些scala REPL,以了解使用它的语法和效果。scala> val s = "Dave"s: java.lang.String = Davescala> val p = s:Objectp: java.lang.Object = Davescala> p.length<console>:7: error: value length is not a member of java.lang.Object       p.length         ^scala> p.getClassres10: java.lang.Class[_ <: java.lang.Object] = class java.lang.Stringscala> s.getClassres11: java.lang.Class[_ <: java.lang.Object] = class java.lang.Stringscala> p.asInstanceOf[String].length
查看完整描述

3 回答

?
回首忆惘然

TA贡献1847条经验 获得超11个赞

类型说明只是告诉编译器,从所有可能的有效类型中,表达式期望什么类型。


如果类型遵守现有约束(例如方差和类型声明),则它是有效的,并且它是表达式所应用的类型之一是“ 是 ”,或者存在适用于范围的转换。


因此,java.lang.String extends java.lang.Object因此String也是Object。在您的示例中,您声明希望将表达式s视为Object,而不是String。由于没有约束可以阻止这种情况,并且所需的类型s 是a的类型之一,因此它可以工作。


现在,你为什么要那样?考虑一下:


scala> val s = "Dave"

s: java.lang.String = Dave


scala> val p = s: Object

p: java.lang.Object = Dave


scala> val ss = scala.collection.mutable.Set(s)

ss: scala.collection.mutable.Set[java.lang.String] = Set(Dave)


scala> val ps = scala.collection.mutable.Set(p)

ps: scala.collection.mutable.Set[java.lang.Object] = Set(Dave)


scala> ss += Nil

<console>:7: error: type mismatch;

 found   : scala.collection.immutable.Nil.type (with underlying type object Nil)

 required: java.lang.String

       ss += Nil

             ^


scala> ps += Nil

res3: ps.type = Set(List(), Dave)

您也可以通过s在ss声明中键入脚本来解决此问题,或者可以将声明ss的类型声明为Set[AnyRef]。


但是,仅在将值分配给标识符时,类型声明才能实现相同的目的。当然,如果一个人不关心用一次性标识符乱扔代码,那哪一个总是可以做的。例如,以下内容不会编译:


def prefixesOf(s: String) = s.foldLeft(Nil) { 

  case (head :: tail, char) => (head + char) :: head :: tail

  case (lst, char) => char.toString :: lst

}

但这确实是:


def prefixesOf(s: String) = s.foldLeft(Nil: List[String]) { 

  case (head :: tail, char) => (head + char) :: head :: tail

  case (lst, char) => char.toString :: lst

}

在此处使用标识符代替会很愚蠢Nil。尽管我可以写List[String](),但这并不总是一种选择。考虑一下,例如:


def firstVowel(s: String) = s.foldLeft(None: Option[Char]) { 

  case (None, char) => if ("aeiou" contains char.toLower) Some(char) else None

  case (vowel, _) => vowel

}

作为参考,这是Scala 2.7规范(2009年3月15日草案)对类型归属的评价:


Expr1 ::= ...

        | PostfixExpr Ascription


Ascription ::= ‘:’ InfixType

             | ‘:’ Annotation {Annotation}

             | ‘:’ ‘_’ ‘*’


查看完整回答
反对 回复 2019-11-27
?
慕森卡

TA贡献1806条经验 获得超8个赞

一种可能性是当网络和串行协议级别的东西出现时,那么:


val x = 2 : Byte

远比


val x = 2.asInstanceOf[Byte]

第二种形式也是运行时转换(不由编译器处理),并且可能导致一些有趣的上溢/下溢情况。


查看完整回答
反对 回复 2019-11-27
?
HUWWW

TA贡献1874条经验 获得超12个赞

类型推断:我们可以跳过在源代码中明确给出某种类型的名称,即类型推断(尽管在某些特殊情况下是必需的)。


Type Ascription:明确表示某种事物的类型称为Type Ascription。它可以带来什么不同?


例如:val x = 2:字节


另请参见:1.我们可以显式地将返回类型赋予函数


def t1 : Option[Option[String]] = Some(None)


> t1: Option[Option[String]]

另一种声明方式可能是:


def t2 = Some(None: Option[String])

> t2: Some[Option[String]]

在这里,我们没有Option[Option[String]]明确给出返回类型,编译器将其推断为Some[Option[String]]。原因Some[Option[String]]是因为我们在定义中使用了类型说明。


我们可以使用相同定义的另一种方法是:


def t3 = Some(None)


> t3: Some[None.type]


这次我们没有明确告诉编译器任何东西(也没有这个定义)。并推断出我们的定义为Some [None.type]


分享编辑


查看完整回答
反对 回复 2019-11-27
  • 3 回答
  • 0 关注
  • 421 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信