奇怪的Ruby类初始化逻辑?

我正在我的应用程序中集成的一些开源代码包含一些包含该效果代码的类:
class SomeClass < SomeParentClass

  def self.new(options = {})
    super().tap { |o|
      # do something with `o` according to `options`
    }
  end

  def initialize(options = {})
    # initialize some data according to `options`
  end

end

据我所知,self.new和initialize都做同样的事情 – 后者“在施工期间”和前者“施工后”,它看起来像一个可怕的模式使用 – 为什么分裂对象初始化为两部分,其中一部分显然是“错误思考(tm)”?

解决方法

理想情况下,我想看看super()里面有什么.点击{| o |阻止,因为虽然这看起来像是不好的做法,但也许在调用initialize之前或之后需要进行一些交互.

如果没有上下文,你可能只是在看一些有效的东西,但在Ruby中并不算是好习惯.

但是,单独的self.new和initialize方法方法可能允许框架设计器实现框架的子类可用部分,并且仍然确保框架所需的设置完成,而不需要特别使用super()的稍微笨拙的文档.如果最终用户仅通过子类MyClass<获得他们期望的功能,那么文档和更干净的API会稍微容易一些. FrameworkClass并没有一些额外的注意事项:

When you implement the subclass initialize,remember to put super at the start,otherwise the magic won’t work

. . .我个人认为这个设计有问题,但我认为至少会有明确的动机.

可能有更深层次的Ruby语言使代码自定义self.new块中运行 – 例如,它可能允许构造函数在返回之前切换或更改特定对象(甚至返回不同类的对象).但是,我很少看到这样的事情在实践中完成,几乎总有一些其他方法来实现这些代码的目标而无需定制新的.

注释中引发的自定义/不同Class.new方法的示例:

> Struct.new,可以选择获取类名并返回该动态创建的类的对象.
> In-table inheritance for ActiveRecord,允许最终用户从表中加载未知类的对象并接收正确的对象.

后者可以通过不同的ORM设计来避免继承(尽管所有这些方案都有优点/缺点).

一个(Structs)是语言的核心,因此必须像现在这样工作(尽管设计者可以选择不同的方法名称).

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...