zoukankan      html  css  js  c++  java
  • Scala Types 2

    存在类型

    • 形式: forSome { type ... }forSome { val ... }

    • 主要为了兼容 Java 的通配符

    • 示例

      Array[_]
      // 等价于
      Array[T] forSome { type T}
      
      Map[_, _]
      // 等价于
      Map[T, U] forSome { type T; type U <: T}
      

    类型系统

    类型 语法
    Class/Trait class C, trait T
    元组 (T1, T2...)
    函数 (P1, P2...) => T
    注解 T @A
    参数类型 A[T1, T2...]
    单例类型 value.type
    类型投射 O#I
    组合类型 T1 with T2 ...
    中缀类型 T1 A T2
    存在类型 T forSome { type/val... }

    以上类型可在编写程序时定义,Scala 也有少量的类型在编译器内部使用

    def square(x: Int) = x * x
    // REPL 中返回的类型为
    // square(x: Int) Int 
    // 省略的方法定义的 => 
    

    自身类型 self type

    • 形式:this: Type =>

    • 用于限制 trait 只能被混编于指定类型的子类中

      trait T1 { def m1()}
      
      trait T2 extends T1 {
      	this: Super1 with Super2 =>
      		def m1() { methodInSuper() }
      }
      
      // 使用时只能在 Super1,Super2 的子类中混编 with T2
      
    • 引入的问题:自身类型不会自动继承,必须在子类中重复定义

      trait T3 extends T2 {
      	this: Super1 with Super2 => // 必须重复定义
      }
      

    依赖注入

    • 通过 trait 和 自身类型 实现简单的以来注入

      • 需要将所有的依赖都组合起来
      trait Logger { def log(msg: String) }
      
      trait Auth {
        this: Logger =>
          def login(id: String, password: String): Boolean
      }
      
      trait App {
        this: Logger with Auth =>
        // ...
      }
      
      object MyApp extends App with FileLogger("test.log") with MockAuth("users.txt")
      
    • 蛋糕模式 (cake pattern) 实现依赖注入

      • 依赖的组件使用自身类型来表示
      • trait 描述服务接口
      • val 定义需要实例化的服务
      • 层级化组合各个组件,在一个整体中注入需要的组件
      // 定义组件1
      trait LoggerComponent {
        // 描述接口
        trait Logger { ... }
        // 需要实例化的服务
        val logger: Logger
        // 接口具体实现
        class FileLogger(file: String) extends Logger { ... }
        ...
      } 
      
      // 定义组件2
      trait AuthComponent {
        // 自身类型限定混编使用的类型
        this: LoggerComponent => // Gives access to logger
        // 定义服务接口
        trait Auth { ... }
        // 需要实例化的服务
        val auth: Auth
        // 接口具体实现
        class MockAuth(file: String) extends Auth { ... }
        ...
      }
      // 所有的依赖都集中在一处进行配置/注入
      object AppComponents extends LoggerComponent with AuthComponent {
        // 实例化服务/注入
        val logger = new FileLogger("test.log")
        val auth = new MockAuth("users.txt")
      }
      

      Scala编程的蛋糕模式和依赖注入

    抽象类型

    • 形式: type Name

    • classtrait 中定义

    • 场景:具体类型需要在子类中确定

      trait Reader {
        type Contents
        def read(fileName: String): Contents
      }
      // 子类实现是具体确定类型
      class StringReader extends Reader {
        type Contents = String
        def read(fileName: String) = ...
      } 
      
      class ImageReader extends Reader {
        type Contents = BufferedImage
        def read(fileName: String) = ...
      }
      
    • 抽象类型、类型参数的使用选择

      • 在类实例化时需要具体确认类型的场景使用类型参数,如 HashMap[String, Int]
      • 期望子类提供具体类型的场景使用抽象类型,如上例中的 Reader

  • 相关阅读:
    085 Maximal Rectangle 最大矩形
    084 Largest Rectangle in Histogram 柱状图中最大的矩形
    083 Remove Duplicates from Sorted List 有序链表中删除重复的结点
    082 Remove Duplicates from Sorted List II 有序的链表删除重复的结点 II
    081 Search in Rotated Sorted Array II 搜索旋转排序数组 ||
    080 Remove Duplicates from Sorted Array II 从排序阵列中删除重复 II
    079 Word Search 单词搜索
    078 Subsets 子集
    bzoj2326: [HNOI2011]数学作业
    bzoj2152: 聪聪可可
  • 原文地址:https://www.cnblogs.com/yuanzam/p/11779880.html
Copyright © 2011-2022 走看看