最近我多次提及module和trait。
粗看,我们可以发现它们有一定的相似处。两者其实都是为了组织代码单元,并在代码上施加更多的约束,且约束的方式有点类似。
目前典型的module是定义require和exports,即需要哪些包(所提供的类和函数),和输出哪些类和函数。
而trait是定义一组方法,并声明这些方法所依赖的方法(即require某些方法)。比如 IterationTrait 可定义 map, filter, reduce, reduceRight 等方法,并声明需要 forEach 方法。这也意味着前些方法内部可能是由forEach方法实现的。
如果看过Ruby语言的设计,就可以理解module和trait的相似性。组合一个trait,就相当于引入一个module。不过我个人并不赞同这样的设计,因为这种相似性只是结构上的。
从概念上说,module和trait两者的共通处是都要强制明确所有的耦合点。区别在于,trait的目的是提供类实现的组合和复用机制,因此其更强制内聚性。module则不带有这个目的。
通常,在module中用到的和输出的函数,都应该是无副作用的(不引起外界可观察到的状态变化)。类,也可视为一种无副作用的函数,因为状态变化被封装到类所产生的对象实例中了,而对象实例是跨模块隔绝的(即对于不同module中创建的对象实例,它们的方法调用只影响它们各自的状态,而不会互相影响)。反过来,要让会引起状态变化的函数也跨模块隔绝相当困难(这意味着被调用函数必须知道它在哪个模块中被调用,这样才能为不同模块保存互相独立的状态)。
这方面的反例是单例(Singleton)。单例通常是跨模块全局的。无正当理由不应使用。
另一个例子是对JS内建对象的prototype的修改。目前的各类模块系统(包括NodeJS)都是不会隔绝的。也就是说,prototype的修改是全局性的,而非局域性的。这也是对内建对象进行prototype扩展必须非常谨慎的根本原因。
而trait通常也应是无状态的。如果有状态,则当前的习惯是使用闭包作为trait的产生器。如果一个trait需要组合其他有状态trait,则它自身通常也随之变为有状态的,也需要套一个闭包作为产生器,产生器接受参数并将参数通过其要组合的trait的产生器传递进去。也就是说,状态是通过产生器被注入进去的。
我本人在一些特殊约束下(如性能考量,因为在产生大量对象时,如果多层trait组合需要大量闭包调用,在IE这样的浏览器中会慢到不可接受),也采用一些折中方式。例如在trait上定义init方法,并通过init方法来初始化状态。当多个具有init方法的trait组合到一起,手工resolve之——实际就是将多个init组合起来。最终init方法应在最终对象实例化后被调用。
当前JavaScript的module系统的设计基本上已经逐渐明晰,其实用性也得到验证。不过trait仍然有很大的发展空间。例如是否应结合type/guard检测?是否trait的手工resolve要求太苛刻而应允许部分妥协(像mixin那样有直接的override机制)?是否应支持私有状态(private)加约定的构造器来取代闭包产生器?诸如此类的问题,可能要等待更多的实践来回答。
分享到:
相关推荐
Laravel开发-trait-maker 创建特征存根的artisan命令
Laravel开发-artisan-trait-maker 创建特征存根的artisan命令
Laravel开发-laravel-trait-uuid 向雄辩模型添加UUID的大型雄辩模型特征
Laravel开发-eloquent-model-trait 为雄辩模型添加有用的方法
计算机后端-PHP大牛线上培训班课-HP设计模式与Trait技术代码复用.mp4
计算机后端-PHP大牛线上培训班课-HP设计模式与Trait技术计模式.mp4
计算机后端-PHP大牛线上培训班课-HP设计模式与Trait技术er安装TP51_Win版.mp4
c语言data和trait.pdfc语言data和trait.pdf
主要介绍了PHP的Trait机制原理与用法,结合实例形式分析了PHP Trait机制的基本功能、原理及简单使用技巧,需要的朋友可以参考下
诸如async-trait ,请避免使用Box和dyn 。 您可以在特征中使用异步键盘输入,而无需分配。 感谢crate ,从中提供了一些代码。 警告:此板条箱使用了一些不稳定甚至不完整的功能。 您将从编译器获得一些警告。 ...
本文实例讲述了PHP Trait代码复用类与多继承实现方法。分享给大家供大家参考,具体如下: 前言 众所周知,一直以来PHP和很多语言一样是单继承的语言,但是常常在编码过程中,我们需要在当前类中使用两个或两个以上的...
rust_and_trait_pub
详细讲解了关于c++模板技术中的trait和policy技术,很值得一看。
a hyperbolic cosine latent trait model for unfolding dichotomous single stimulus responses
说通俗点,PHP中使用trait关键字是为了解决一个类既想集成基类的属性和方法,又想拥有别的基类的方法,而trait一般情况下是和use搭配使用的。 <?php trait Drive { public $carName = 'trait'; public ...
Laravel开发-validation-trait Laravel的验证特性
鸡尾酒特质可配置 特性扩展 添加configure(options)方法的特征,该方法将在每个选项键上调用设置器。... '@exports' : module , '@as' : 'class' , '@traits' : [ Configurable ] , '@propert
本文实例讲述了Laravel中Trait的用法。分享给大家供大家参考,具体如下: 看看PHP官方手册对Trait的定义: 自 PHP 5.4.0 起,PHP 实现了代码复用的一个方法,称为 traits。 Traits 是一种为类似 PHP 的单继承语言而...
自PHP5.4.0起,PHP实现了一种代码复用的方法,称为Trait。因为PHP是单继承,当你需要多个区别的特性,就不得不去组合多个基类,Trait出现后就避免了这些问题,Trait的优势就是可以随意组合,而且代码清晰。本文主要...