返回介绍

数学基础

统计学习

深度学习

工具

Scala

十、模块化编程

发布于 2023-07-17 23:38:23 字数 3507 浏览 0 评论 0 收藏 0

  1. package 和访问修饰符能够让你把包当做模块 module 来组织大型程序。这里的模块指的是具有良好定义的接口以及隐藏实现的 ”小程序片段“。

  2. 任何致力于模块化都需要满足一些最基本的要求:

    • 首先,应该有一个能够很好地分离接口和实现的模块结构
    • 其次,应该有方式可以替换具有相同接口的模块,而不需要改变或者重新编译依赖该模块的其它模块
    • 最后,应该有方式可以将模块连接在一起。这种连接操作可以认为是在配置该系统。
  3. 解决模块化的一种思路是依赖注入dependency injection,这是一种通过框架来支持的、构建在 Java 平台上的技术。

    尽管也可以在 Scala 里使用 Spring ,从而以 Spring 的方式让scala 程序模块化,但是在scala 中还有其它选择:将对象当做模块来使用,无须任何额外的框架从而达到模块化的目的。

  4. Scala 用对象来表示模块,因此程序可以被切分成单例对象,每个单例对象表示一个模块。单例对象中的一些 private 元素是模块实现的一部分,这可以在不影响其他模块的情况下进行修改。

  5. 混入特质时,可以通过 self type 来处理跨特质的引用。

    
    
    xxxxxxxxxx
    abstract class Food(val name: String) { override def toString = name } ​ object Orange extends Food("orange") ​ trait A{ object Apple extends Food("apple") ... } ​ trait B{ val list = List(Apple,Orange) // Apple 不在作用域内 ... }

    在特质 B 中引入 Apple 时出现问题,因为 Apple 作用在特质 A 中,因此超出了作用域。

    此时可以在特质中引入 self type。从技术上讲,self type 是在类中提到 this 时,对 this 预期的类型。从实际应用来讲, self type 指定了对于特质能够混入的具体class 的要求。

    例如:

    
    
    xxxxxxxxxx
    trait B{ this: A => val list = List(Apple,Orange) // Apple 现在在作用域内 ... }

    现在要求任何混入 Bclass 也必须混入 A 。现在 Apple 被隐含地认为是 this.Apple 了。

    注意:抽象子类和抽象特质不必遵循这个限制,因为它们不能被 new 实例化,所以并不存在 this.Apple 引用失败的风险。

  6. 结尾为 .type 的类型表示单例类型。单例类型极为明确:这个类型只保存一个对象。通常这样的类型太过于确定,以至于没什么用处。

    通常它用于链式调用:

    
    
    xxxxxxxxxx
    class A{ def f1: A = this } class B extends A{ def f2: B = this } val b = new B b.f2.f1 // 可以调用 b.f1.f2 // 无法调用

    其中 b.f1.f2 无法调用,因为 b.f1 返回的类型为 A,而 A 是不存在 f2 方法的。

    解决的办法就是单例类型:

    
    
    xxxxxxxxxx
    class A{ def f1: this.type = this } class B extends A{ def f2: this.type = this } val b = new B b.f2.f1 // 可以调用 b.f1.f2 // 可以调用

    现在 b.f1 返回的类型就是当前实例的单例类型,这个单例类型只要唯一的实例对象 b

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文