Steve Klabnik最近在一个实用程序模块的拉取请求中说:
[代码]模糊了这些是类方法的事实,我们希望以这种方式使用它们.另外,我认为这
extend self
通常是一种反模式,除非在某些情况下,否则不应该使用.我想到了,我认为这是其中一个案例.
extend self
成语适合?Rus*_*ell 24
他没有说1)为什么他认为这是一种反模式(除了模糊你定义类方法的事实)或2)为什么,考虑到它,这是其中一个案例并不完全有用他认为不应该使用它,因此很难专门反驳他的任何论点.
但是,我不相信这extend self
是一种反模式.实用程序模块似乎是一个用例的好例子.我也用它作为测试夹具的简易存储.
我认为值得研究一下extend self
,它可能存在哪些问题,以及有哪些替代方案.
在它的核心,它只是一种避免必须self.
在模块中的每个方法定义之前编写的方法,你永远不打算混合到一个类中,因此永远不会创建自己的"实例",因此只能定义有'类'方法(如果你想能够调用它们,那就是).
它是否掩盖了您希望将方法用作类方法的事实?嗯,是的,如果你不看文件的顶部到它所说的位置extend self
,那是可能的.但是,我认为,如果你有可能让这种混乱,你的课程可能太复杂了.
从你的班级 - 从名称和内容 - 中可以明显看出它是作为效用函数的集合.理想情况下,无论如何它都不会超过屏幕高度,所以extend self
几乎永远不会出现在视线之外.正如我们所看到的,替代方案也会遇到几乎完全相同的问题.
一种替代方法是使用class << self
这样的:
module Utility
class << self
def utility_function1
end
def utility_function2
end
end
end
Run Code Online (Sandbox Code Playgroud)
我不是这个的粉丝,尤其是因为它引入了额外的缩进层.它也很难看(完全主观,我知道).它也会遇到完全相同的"模糊"你正在定义类方法这一事实的问题.
使用这种方法你也可以自由地定义class << self
块外的实例方法- 这可能会导致这样做的诱惑(虽然我希望它不会),所以我认为extend self
在这方面是优越的通过消除这种混乱的水的可能性.
(当然,"长手"使用方式也是如此def self.utility_function
.)
另一种方法可能是使用单例对象.我认为这根本不是一个好主意,因为单个对象是一个理由的对象 - 它意味着保持状态和做事,但也是唯一存在的对象.这对于实用程序模块来说根本没有意义,它应该是一系列独立的无状态函数.您不希望MathUtils.cos(90)
根据内部状态返回不同的值MathUtils
,对吧?(我知道你当然可以在模块中保存状态并完成所有这些事情,但它对我来说更像是一个语义划分而不是技术划分).
它也导致同样的问题,即可以说是模糊了这些方法被称为类方法(类型)的事实.它们被定义为实例方法,您将它们称为实例方法,但首先通过调用类方法获取类的单个实例instance
.
class MathSingleton
include Singleton
def cos x
end
end
MathSingleton.instance.cos x
Run Code Online (Sandbox Code Playgroud)
extend self
对于这个目的,这将是一个可怕的替代方案.但是,看起来,唯一的事情表明这些方法将被用作单例实例上的方法是一行只是在顶部,就像extend self
.
那么还有其他可能的缺点呢?我不知道有什么,但如果有其他人这样做,我会有兴趣听到它们.
我认为这extend self
会导致更短的代码,从而省去了无关self.
的代码,并允许您专注于名称及其方法的含义.
它还具有很好的属性,例如,如果您正在编写另一个使用大量实用程序功能的类,您可以将其混合使用,并且每次都可以使用它们而无需使用模块名称.就像静态导入在其他语言中一样.
归档时间: |
|
查看次数: |
4291 次 |
最近记录: |