gpt4 book ai didi

Ruby 向类添加方法

转载 作者:数据小太阳 更新时间:2023-10-29 06:45:19 25 4
gpt4 key购买 nike

假设我有一个类:

class Foo
end

要向此类添加方法,我知道 2 个选项:

  1. 重新打开类并实现方法:

    class Foo
    def bar
    end
    end
  2. 使用class_eval 实现方法:

    Foo.class_eval { def bar; end}

有什么区别?哪个更好?

最佳答案

实际上,还有一些其他方法可以向类中添加新方法。例如,您也可以在模块中定义方法,并将模块混入原始类中。

module ExtraMethods
def bar
end
end

Foo.class_eval { include ExtraMethods }
class Foo
include ExtraMethods
end

没有真正的好或坏。您提到的两种(或三种)方式具有不同的行为,您可能希望根据您的需要(或偏好)使用一种或另一种方式。在大多数情况下,这是主观的。在其他情况下,这实际上取决于代码的结构。

重新打开类与使用 class_eval 之间的主要客观区别是第一个也是类定义,而第二个需要已经定义了原始类。

在实践中,在某些情况下重新打开类可能会导致一些意想不到的副作用。假设您在文件 lib/foo.rb 中定义了 Foo,其中包含一系列方法。然后在 config/initializers/extra.rb 中重新打开 Foo 并添加 bar 方法。

myclass.rb 中,您使用 Foo,但您不需要手动请求 lib/foo.rb,而是依靠自动加载功能。

如果 extra.rblib/foo.rb 之前加载,可能发生的情况是 Foo 类已经定义在您的环境,您的代码将不会加载 lib/foo.rb。您将拥有一个 Foo 类,它只包含您定义的 bar 扩展,而不是原始的 Foo

换句话说,如果出于某种原因您重新打开该类以添加一些方法,而没有确保首先(或之后)加载完整的原始类定义,如果它依赖于自动加载,您的代码可能会中断。

相反,Foo.class_eval 调用 Foo 上的方法,因此它期望原始的 Foo 定义在您执行时已经存在尝试添加新方法。这确保了当您添加新方法时,Foo 类已经被定义。

总之,主要区别在于重新打开类允许您(无论好坏)向可能尚未加载的类添加方法,而 class_eval 需要类已经被定义。

一般来说,除非我正在定义命名空间子类或重新打开我完全控制的类,否则我更喜欢第二种方法,因为在大型代码库中它使代码更易于维护。事实上,如果我扩展第三方类,我通常会使用 mixin,这样我可以在需要覆盖现有方法时保留完整的方法祖先链。

关于Ruby 向类添加方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34528649/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com