当前位置:  开发笔记 > 后端 > 正文

Ruby将方法添加到类中

如何解决《Ruby将方法添加到类中》经验,为你挑选了2个好方法。

假设我有一个班级:

class Foo
end

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

    重新打开该类并实现该方法:

    class Foo
      def bar
      end
    end
    

    通过class_eval实施方法:

    Foo.class_eval { def bar; end}
    

有什么不同?哪一个更好?



1> Simone Carle..:

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

module ExtraMethods
  def bar
  end
end

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

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

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

在实践中,在某些情况下重新打开课程可能会导致一些意想不到的副作用.假设您使用一堆方法Foo在文件中定义lib/foo.rb.然后重新打开Fooconfig/initializers/extra.rb你添加的bar方法.

myclass.rb您使用时Foo,您需要lib/foo.rb依靠自动加载功能,而不是手动操作.

如果extra.rb之前加载了lib/foo.rb,那么可能发生的是Foo该类已在您的环境中定义,并且您的代码将无法加载lib/foo.rb.您将拥有的是Foo仅包含bar您定义的扩展名的类,而不是原始扩展名Foo.

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

相反,Foo.class_eval调用方法Foo,因此它希望在Foo您尝试添加新方法时已经存在原始定义.这可以确保在添加新方法时,Foo已经定义了类.

总而言之,主要区别在于重新打开类允许您(无论好坏)将方法添加到可能尚未加载class_eval的类中,而要求已经定义类.

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



2> Зелёный..:

当你需要一些动态的东西时,第二种方法非常方便.Ruby实际上有几个范围:

# scope one, opened with `class` keyword
class ...
  # scope two, opened with `def` keyword
  def ...
  end
end

有了class_eval,您可以共享范围.

>> foo = 1
=> 1
>> class Foo
>>   puts foo
>>   def bar
>>     puts foo
>>   end
>> end
NameError: undefined local variable or method 'foo' for Foo:Class
        from (irb):3:in 
        from (irb):2
>> Foo
=> Foo
>> Foo.class_eval {
?>   puts foo
>>   define_method :bar do
>>     puts foo
>>   end
>> }
1
=> :bar
>> Foo.new.bar
1

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有