在 Ruby 模块中使用"扩展自我"和"类<<自身" 如何检查生成的元素流中可能包含的 2 个或更多值的内容 - Flux<T> (Spring WebFlux)



我有时会编写只包含模块方法的模块(与模块实例方法相反)(有更好的名称吗?)。这些模块不应该包含在类中,因为这不会产生任何影响,并且会误导读者。因此,我希望读者尽可能清楚地知道,这些模块不包含实例方法。

如果我用.self定义所有方法,那么读取器必须检查所有方法,以确保该模块不包含实例方法。如果我改为使用class << selfextend self,则它是自动的;读者一看到这个就知道了。

我认为extend self是最好的,因为class << self必须找到它对应的end;也就是说,它可能不适用于模块中的所有方法。

那么,在这种情况下使用extend self是一个好主意,也是一种最佳实践吗?

此外,在运行时,将所有方法封装在class << self中与使用extend self之间有什么区别吗?

我有时会编写只包含模块方法(与模块实例方法相反)的模块(有更好的名称吗?)。

Singleton,意思是具有单个实例的类。在这里;"单个实例";是Module实例。

如果我用.self定义所有方法,那么读取器必须检查所有方法,以确保该模块不包含实例方法

模块的文档应该说明这一点。如果模块的用户必须学习代码才能理解您的模块,那就是文档失败。

extend self的作用是什么

所以我希望读者尽可能清楚地知道,这些模块不包含实例方法

extend self的作用正好相反。它使所有实例方法也是类方法。它相当于YourModule.extend(YourModule)

module YourModule
def some_method
23
end
extend self
end

与…相同

module YourModule
def some_method
23
end
end
YourModule.extend(YourModule)

类似于…

module YourModule
def some_method
23
end
def self.some_method
23
end
end

你为什么要这么做?要同时允许。。。

YourModule.some_method

而且。。。

class SomeClass
extend YourModule
end
SomeClass.some_method

在某些边缘情况下,你可能想要这样做,但对于一般用途,我认为这是一种反模式。第一种是将模块用作单例,第二种是将该模块用作mixin或trait。这是一个模块的两个截然不同的设计目标。两者兼而有之会影响两者的设计。

优点和缺点

由于同时是singleton和mixin的主要用例是反模式的,所以我认为偶尔使用class << selfdef self.method,从不使用module_functionextend self

class << self

Pros

  • 所有类定义都分组在一起
  • 块作用域清楚地表明了什么影响类,什么影响实例
  • 缩进可以清楚地显示块中的内容
  • IDE可以清楚地识别块中的内容
  • 它允许在类上使用像attr_accessor这样的普通声明
  • 它是有文件记录的
  • 这很常见
  • Rubocop批准

Cons

  • 当观察单个方法时,它不如def self.method那么明显

def self.method

Pros

  • 从方法的角度来看,这显然是一个类方法
  • 它是有文件记录的
  • 这很常见
  • Rubocop批准

Cons

  • 您可能忘记添加self.
  • 它允许混合类和实例方法,使读者在代码中搜寻
  • 在课堂上使用attr_accessor和朋友并没有帮助

extend self

Pros

  • 它允许您的模块同时充当singleton(YourModule.method)和mixin(extend YourModule)。。。这也是一个骗局

Cons

  • 它是模糊的;许多人(大多数人?)不知道该找它,也不知道如果找到了它意味着什么
  • 它没有记录(或者如果有,我找不到它)
  • 单个方法看起来像实例方法
  • 它可以出现在模块中的任何地方,并且没有达成一致意见,使它在远处发挥作用
  • 它影响了之前的代码的含义,这是我在Ruby中可以想到的一种情况,进一步使它在远处起作用
  • Rubocop更喜欢module_function而不是extend self,但没有解释原因。我的猜测见下文
  • 它允许您的模块同时充当singleton(YourModule.method)和mixin(extend YourModule)。这是两个截然不同的用例,使其成为反模式

module_function

我也从来没有听说过这个,但它是在搜索extend self时出现的。我也会说永远不要使用这个,使用class << self,但它比extend self更好。

Pros

  • 它至少在模块和类文档中提到过
  • 它是有文件记录的
  • 它的工作原理与private类似,因为它影响它下面的所有方法(尽管这也是一个骗局,请参阅下文)
  • 如果没有实例方法,它必须出现在模块的顶部
  • Rubocop批准

Cons

  • 它是模糊的;许多人(大多数人?)不知道该找它,也不知道当他们找到它时它意味着什么
  • 单个方法看起来像实例方法
  • 它使远程代码在一段距离内起作用后,会影响远程代码的含义

我不明白为什么决定如何定义模块方法很重要。如果模块包含在另一个模块(可能是一个类)中,请考虑简单地引发异常。您可以使用回调(也称为"钩子")方法Module#来实现这一点。下面是一个例子。

module M
# This module is not to be included in a class because
# it contains no instance methods.

def self.included(klass)
raise "nYou intended to include this module in #{klass}. You must be out ofnyour mind! It does no harm but there is no point in doing sonbecause this module contains no instance methods. Duh!"
end

def self.hi
puts "Hi, guys"
end
end
M.hi
Hi, guys
class C
include M
end
RuntimeError: 
You intended to include this module in C. You must be out of
your mind! It does no harm but there is no point in doing so
because this module contains no instance methods. Duh!

相关内容

最新更新