经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Scala » 查看文章
Scala Types 1
来源:cnblogs  作者:afewnotes  时间:2019/10/30 9:18:00  对本文有异议

在 Scala 中所有值都有一种对应的类型

单例类型

  • 形式:value.type,返回类型 value / null
  • 场景1:链式API调用时的类型指定

    1. class Super {
    2. def m1(t: Int) = {println(t); this}
    3. def m2(t: Int) = {println(t); this}
    4. }
    5. // 正常打印
    6. new Super().m1(1).m2(2)
    7. class Child extends Super {
    8. def c1(t: Int) = {println(t); this}
    9. }
    10. // 异常 value c1 is not a member of Super
    11. new Child().m1(1).c1(2)

    由于 Scala 会将 this 推断为当前类(即 Super),因此无法完成链式调用

    1. class Super {
    2. // 指定返回类型为调用方的 this
    3. def m1(t: Int): this.type = {println(t); this}
    4. def m2(t: Int): this.type = {println(t); this}
    5. }
    6. class Child extends Super {
    7. def c1(t: Int) = {println(t); this}
    8. }
    9. // 成功打印
    10. new Child().m1(1).c1(2)
  • 场景2:方法中使用 object 实例作为参数

    1. object Foo
    2. class Child extends Super {
    3. def c1(obj: Foo.type) = {
    4. if (obj == Foo) println("foo")
    5. this
    6. }
    7. }

    Note:不可定义为 def c1(obj: Foo),因为 Foo 为单例对象,而不是类型

类型投影

  • 形式:Outer#Inner
  • 场景:内部类使用时避免类型约束

    1. class Outer {
    2. private val inners = ArrayBuffer[Inner]()
    3. class Inner (val arg1: Int) {
    4. val l = ArrayBuffer[Inner]()
    5. }
    6. def add(a: Int) = {
    7. val t = new Inner(a)
    8. inners += t
    9. t
    10. }
    11. }
    12. val a = new Outer
    13. val b = new Outer
    14. val a1 = a.add(1)
    15. val b1 = b.add(1)
    16. a1.l += b1 // error: type mismatch;

    只需要在定义内部类时指定类型投影即可解决

    1. // 表示适用于任何 Outer 类的 Inner 类
    2. val l = ArrayBuffer[Outer#Inner]()

    如果将上述例子改用 List 来实现,并不会报错,计算结果也会自动进行类型投射

路径

  • 路径中除最后一部分外,都必须是稳定状态的,如包名、objectvalthis/super/super[S]...
  • 不能包含 var 类型

    1. var t = new Outer()
    2. //...其他操作
    3. val i = new t.Inner // 由于 t 可能会变更,编译器无法确定其含义

    a.b.c.T 内部被翻译成类型投射 a.b.c.type#T

类型别名

  • 形式: type SomeAliasName
  • 必须定义在 classobject 内部
  • 好处: 在引用类型时可以更加简洁

    1. class Book {
    2. import scala.collection.mutable._
    3. // 为该类型取一个别名
    4. type Index = HashMap[String, Int]
    5. // 使用时不在需要重复的定义复杂的数据类型
    6. val map: Index = new Index()
    7. }
    8. new Book().map // scala.collection.mutable.HashMap[String,Int]

结构类型

  • 为抽象方法、字段、类型的定义某种规范

    1. def appendLines(target: { def append(str: String): Any },
    2. lines: Iterable[String]) {
    3. for (l <- lines) {
    4. // 此次 Scala 使用反射调用该方法
    5. target.append(l);
    6. target.append("\n")
    7. }
    8. }

    该方法第一个参数 target 即结构类型,表示使用任何包含该 append 方法的实例作为参数传入。

    由于反射的代价较大,不到万不得已不建议使用,如,有通用行为(append),却无法共享 trait

组合类型 / 交集类型

  • 形式: T1 with T2 with T3 ...
  • 当需要提供多个特质时使用,即用于约束类型

    1. val image = new ArrayBuffer[java.awt.Shape with java.io.Serializable]
    2. val rect = new Rectangle(5, 10, 20, 30)
    3. image += rect // 正确,Rectangle 可序列化
    4. image += new Area(rect) // 错误 Area 不可序列化
  • 组合类型中也可使用结构类型

    1. Shape with Serializable { def contains(p: Point): Boolean }

中缀类型

  • 其实只是一种语法写法,如 String Map Int 可代替 Map[String, Int]
  • 可参考数学运算中的表达方式

    1. type x[A, B] = (String, Int)
    2. // 即可使用 String x Int 来表示 (String, Int)
  • 一般中缀类型操作符都是左关联的,除了前面提到的 : 操作符,这个是右关联的,比如 List 的操作

中缀类型名称可以是任意操作符,除了 *,避免与类型定义冲突

原文链接:http://www.cnblogs.com/yuanzam/p/11761509.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号