惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News and Events Feed by Topic
爱范儿
爱范儿
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 叶小钗
Last Week in AI
Last Week in AI
博客园 - 三生石上(FineUI控件)
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - Franky
人人都是产品经理
人人都是产品经理
The Cloudflare Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 司徒正美
罗磊的独立博客
博客园 - 聂微东
T
Troy Hunt's Blog
美团技术团队
IT之家
IT之家
A
Arctic Wolf
腾讯CDC
雷峰网
雷峰网
SecWiki News
SecWiki News
博客园_首页
L
LINUX DO - 最新话题
Cloudbric
Cloudbric
量子位
N
News and Events Feed by Topic
小众软件
小众软件
C
CXSECURITY Database RSS Feed - CXSecurity.com
Cyberwarzone
Cyberwarzone
J
Java Code Geeks
V
V2EX
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Latest news
Latest news
Webroot Blog
Webroot Blog
F
Fortinet All Blogs
P
Privacy International News Feed
NISL@THU
NISL@THU
Google Online Security Blog
Google Online Security Blog
WordPress大学
WordPress大学
PCI Perspectives
PCI Perspectives
GbyAI
GbyAI
宝玉的分享
宝玉的分享
阮一峰的网络日志
阮一峰的网络日志
S
Secure Thoughts
Simon Willison's Weblog
Simon Willison's Weblog
P
Palo Alto Networks Blog
V
Visual Studio Blog

夜行人

回家路上 第一期的直播演示项目 震动检测器 正能量 在线参观CodeLab Neverland 发布 CodeLab Adapter 3.3.1 DynamicTable 之 纸糊方向盘 CodeLab DynamicTable: 一个可实施的技术方案 CodeLab Insight 发布 Alpha 版 情人节 Home Assistant 周报 && IoT 周报 (02) Joplin: 关注隐私的 Evernote 开源替代软件 浏览器的未来与 Web 传感器 Home Assistant 周报 && IoT 周报 (01) 百宝箱(01) 论自由 介绍 WebThings Home Assistant 周报 && iot 周报 (00) 百宝箱(00) 毛姆读书心得 传世之作 周末徒步 CodeLab Adapter ❤️ Jupyter/Python 航班 躲雨 夏令营途中 [译]思想--作为一种技术 The future of coding 美国之行 三门问题的程序模拟 从Python转向Pharo https://blog.just4fun.site/post/iot/iot-open-source-projects/ Python异步编程笔记 https://blog.just4fun.site/post/iot/iot-open-source-hardware-community/ 万物积木化开发者社区 CodeLab ❤️ Blender Scratch3技术分析之云变量 API(第7篇) [译]对管道(Pipes)的偏爱 [译]提出正确的问题比得到正确答案更重要 蓝牙设备与Scratch3.0 创建你的第一个Scratch3.0 Extension Scratch3技术分析之项目内部数据(第6篇) Scratch3技术分析之社区 API(第5篇) Scratch3技术分析之User API(第4篇) Scratch3技术分析之项目主页API(第3篇) Scratch3技术分析之静态资源API(第2篇) Scratch3.0、micro:bit与Windows7 https://blog.just4fun.site/post/iot/zerynth-vs-micropython/ 核聚变、方所与半宅空间 可视化编程为何是个糟糕的主意 codelab.club周末聚会 关于codelab.club '下一件大事'是一个房间 Hungry Robot - Eat everything 编程作为一种思考方式 今日简史 史蒂夫·乔布斯传 罗素自选文集 https://blog.just4fun.site/post/edx/tianjin-scratch-ai/ https://blog.just4fun.site/post/edx/richie-cms-openedx/ 徒步武功山 WebUSB与micro:bit 积木化编程与3D场景 夜宿武功山顶 scratch3-adapter接入优必选Alpha系列机器人 https://blog.just4fun.site/post/edx/video-migration-note/ scratch3-adapter重构笔记 https://blog.just4fun.site/post/edx/edx-community-members/ 两种硬件编程风格的比较 使用micro:bit自制PPT翻页笔 柏拉图对话集 scratch3.0 + micro:bit 七月电影放映计划 非营利组织的管理 Screenly--用树莓派让任何屏幕变为可编程的数字标牌 以最佳实践开始你的Django项目 micro:bit与事件驱动 为Scratch3.0设计的插件系统(上篇) OCR应用一例 近两年读过的一些好书 blockly开发之使用python驱动浏览器中的turtle(2) 牛顿新传 文学理论入门 逻辑的引擎 人生的意义 blockly开发之生成并运行js代码(1) blockly开发之hello world(0) micro:bit使用笔记 神器之Termux https://blog.just4fun.site/post/iot/micropython-notes/ Cozmo what is this Scratch的前世今生 下段旅程 我行在远方 爆裂 途中杂记 https://blog.just4fun.site/post/edx/open-edx-startup/ cozmo系列之入门 - 有性格且可编程的机器人 PaperWeekly开发笔记 创业二三事
使用 Traits 复用行为
种瓜 · 2022-08-26 · via 夜行人

文章目录

Traits 是面向对象编程中使用的概念,它表示一组用于扩展类的功能的方法 – wikipedia Trait

Traits 最初在 Smalltalk 里被发明出来,后来有不少编程语言都实现了它:

Traits 是由 Nathanael Schärli 和他的合作者设计和实施的,时间发生在 2000 年 他在 Alan Kay 手下的实习期间。我在同一时间也在那儿实习。我有机会看到这项工作的进展情况。
这个版本的 Traits 最初是在 Smalltalk 的背景下构思的,但是它简洁的特性吸引了很多其他的语言设计者 – Yoshiki Ohshima

最佳读物

理解 Traits 的最佳读物是 Traits: Composable Units of Behaviour, 这篇论文清晰而详细讨论了 Traits 试图解决的问题和它的基本想法。 以下是我阅读时做的摘录。

这些摘录主要供我自己日后复习用,如果你想获得对 Traits 的全面认识,建议去阅读论文原文。

Abstract

  • 尽管继承作为面向对象编程语言的基本重用机制具有无可争议的重要性,但其主要变体–单继承、多继承和混合继承–都存在着概念层面和实际层面的问题。

  • Traits 是一个简单的用于构造面向对象程序的组合模型。Traits 本质上是一组纯方法(译者注: 不包含状态(如实例变量)),作为类的构建模块,是代码重用的原始单元。

1 Introduction

  • 单继承的表现力不足以将复杂层次结构中的类所共享的共同特征(即实例变量和方法)考虑进去。因此,语言设计者们提出了各种形式的多重继承, 以及其他机制,如 mixins, 允许类从特征集中逐步组成。

  • 类经常不是最合适的重用代码的元素,因为类扮演着两个相互竞争的角色。类的主要作用是作为实例的生成者:因此它必须是完整的。但作为一个重用的单位,类应该是小的。这些特性经常发生冲突。此外,类作为实例生成器的作用要求每个类在类的层次结构中有一个独特的位置,而重用的单位应该在任意的位置适用。

  • 继承要求 mixins 以线性方式组成;这严重限制了人们指定 “胶水代码” 的能力,而 “胶水代码” 是调整混合体以使它们适合在一起所必需的。

  • Traits 的设计始于这样的观察:重用和可理解性之间的冲突比实际情况更明显。一般来说,我们认为,如果能够以多种形式来看待一个程序,那么理解该程序就会更容易。即使一个类可能是由一个复杂的层次结构中的小 Traits 组成的,也没必要要求以同样的方式来看待它。我们应该可以把类看作是一个扁平的方法集合,或者看作是一个由 Traits 构成的组合实体。扁平化的观点促进理解;组合的观点促进重用。只要这两种观点能够共存,就不会有冲突,这就要求组合只作为一种结构化工具,对类的意义没有影响。

  • Traits 有以下特性:

    • 一个 Trait 提供了一套实现行为的方法。

    • 一个 Trait 需要一组方法来作为它(Trait)所提供的行为的参数

    • Traits 不指定任何状态变量,Traits 提供的方法也从不直接访问状态变量。

    • 类和 Traits 可以由其他 Traits 组成,但组成顺序是不相关的。冲突的方法必须被明确解决。

    • Traits 组合不影响类的语义:如果从 Traits 中获得的所有方法都直接在类中定义,那么类的意义是一样的。

    • 同样地,Traits 的组合也不影响 Traits 的语义:一个复合 Traits 等同于一个包含相同方法的扁平化 Traits。

3 Traits

3.2 Specifying Traits

  • Traits 可能需要一组方法来作为它(Trait)所提供的行为的参数。Traits 不能指定任何状态,也不能直接访问状态。Traits 方法可以间接地访问状态,使用最终由访问器(accessors)(getter 和 setter 方法)满足的依赖方法(required methods)。

图3. Traits TDrawing 和 TCircle,左栏是提供的方法,右栏是依赖的方法(required methods)。
  • 在我们的例子中,每个图形对象可以被分解成两个方面–它的几何形状,以及它在画布上的绘制方式。对于一个圆,我们用 trait TCircle 表示其几何形状,用 trait TDrawing 表示其绘制行为。

3.3 Composing Classes from Traits

  • Traits 是对单一继承的补充,而不是对单一继承的取代。 继承是用来从另一个类中派生出一个类,而 Traits 是用来实现类定义中的结构和重用性

  • Class = Superclass + State + Traits + Glue

图4. Circle 类由 traits TCircle 和 TDrawing 组成。`TDrawing>>bounds` 的要求由 trait TCircle 来实现。所有其他的要求都由该类的访问器方法来实现。
  • 这意味着类从超类中派生出来,通过添加必要的状态变量,使用一组 traits,并实现连接 traits 的胶合方法,作为状态变量的访问器。为了使类变得完整,必须满足 traits 的所有要求,即必须提供具有适当名称的方法。这些方法可以在类本身、直接或间接的超类中实现,或者由类所使用的另一个 trait 实现。

  • 在类中定义的方法和由并入的 traits 定义的方法之间的冲突是通过以下两条优先规则解决的

    • 类方法优先于 trait 方法。

    • trait 方法优先于超类方法。这源于扁平化属性,它指出 traits 方法的行为就像它们被定义在类本身中一样。

3.4 Composite Traits

  • 就像类是由 traits 组成的一样,traits 也可以由其他 traits 组成。与类不同的是,大多数 traits 并不完整,这意味着它们没有定义其子 traits 所要求的所有方法。子 traits 中未满足的要求只是成为复合 trait 的必要方法。同样,组合顺序并不重要,复合 traits 中定义的方法优先于其子 traits 的方法。

  • trait TCircle 包含两个不同的方面:比较运算符和几何函数。为了分离这些方面并提高代码的重用性,我们把这个 trait 重新定义为 trait TMagnitude 和 TMGeometry 的组合

4 Discussion and Evaluation

  • 细粒度的重用很重要,因为整个类和单个方法之间的差距太大。traits 允许通过组合可重用的行为来构建类,而不是通过实现大量非结构化的方法集。层次独立是很重要的,因为它可以最大限度地提高重用性。因为类的主要作用是作为实例生成器,它们必须是完整的,因此通常被嵌入到一个层次结构中。这一特性使得类不适合于它们在传统语言中扮演的次要角色:可重用的方法库。

Squeak 中的 Traits

翻译自 Squeak by Example > 5.4 > Traits

简单例子

要定义一个新的 trait,只需将子类的创建模板替换为发送给 Trait 类的消息。

1
2
3
Trait named: #TAuthor
uses: { }
category: 'Trait-Demo'

Traits 可以包含方法,但不能包含实例变量

1
2
3
TAuthor»author
"Returns author initials"
^ 'taa' "the anonymous author"

现在我们可以在一个普通类中使用这个 trait

1
2
3
4
5
6
Morph subclass: #TestBook
uses: TAuthor
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Trait-Demo'

实例化 TestBook 之后,就可以发送 author 消息

TestBook new author −→ 'taa'

常见问题

  1. 怎样找到系统中的所有 Traits ?
  1. 怎样找到哪些类使用 Traits?
1
Smalltalk allClasses select: [:each | each hasTraitComposition]

附录

扩展类/对象的行为的机制

值得注意的是, Yoshiki 提到大约在 Traits 正在设计的时候, Etoys 也启动了,Etoys 中可插拔的方法的理念类似于 Traits,但有一些关键的区别, 最重要的是,它是基于实例而不是基于类的机制;它用于增强用户关心的具体对象(即,这是用户自己的绘图),而不是你用来构建抽象结构然后从中创建实例的东西。 如果你对构建灵活的终端用户编程环境感兴趣,Etoys 非常值得学习,它可能是迄今为止最出色的终端用户编程环境之一,Squeak 6.0 非常好地整合了 Etoys。

你可以从 Player 类入手来理解 Etoys 的设计, 这是我目前的做法。重要的不是阅读类的静态代码,这是极为低效的,抛弃过去在其他语言里养成的这些弱小习惯,试着融入 Smalltalk 文化,去跟活的(live)对象一起玩耍,然后深入它们。

参考