我尝试使用模块将我自己的方法添加到 Array 类中(但不覆盖它)


class Check 
  include TestParser
  # so on
end

和模块结构:

module TestParser
  class Array
    def parse_test
      # method
    end
  end
end

我想要实现的是,文件check.rb中的每个数组都可以通过parse_test方法调用。

我哪里做错了?(抛出未定义的方法错误)

你正在寻找的是Ruby 2.0的改进。请注意,此功能是实验性的:

module TestParser
  refine Array do
    def parse_test
      42
    end
  end
end
using TestParser  # This applies only to the current file
class Check
  [].parse_test  #=> 42
end

您也可以从 Array 继承并添加您的方法:

class TestParser < Array
  def parse_test
    42
  end
end
arr = TestParser.new
arr.is_a? Array  #=> true
arr.parse_test   #=> 42

但是,我强烈建议不要做这两件事。最好创建一个封装数组的对象,并且只提供您需要的方法:

class TestParser
  def initialize array = []
    @array = array
  end
  def parse_test
    # do stuff to @array
  end
end

最后,为什么你拥有的东西不起作用:

module TestParser
  class Array
    def parse_test; end
  end
end

创建两件事:一个没有方法的模块TestParser和一个带有一个方法的类TestParser::Arrayparse_test)。由于TestParser没有方法,因此将其包含在另一个模块/类中对可用方法没有影响。包括TestParserTestParser::Array没有任何作用。

您已经定义了一个包含 parse_test 方法的新类TestParser::Array;您尚未修改Array类。

您也可能混淆模块和包含。

如果您的目标是将方法parse_test添加到 Ruby 程序中的数组中,则可以将其放在名为 test_parser.rb 的文件中,无需模块声明:

class Array  
  def parse_test
    # method
  end
end

但这会修改基Array类,你说你不想这样做。此外,它将在文件require d后立即进行该修改。 无需包含。

除了当前实验性的 Ruby 2.0 功能(称为改进)之外,没有办法将这些类型的修改本地化为基类(称为"猴子修补")。

如果您希望数组的行为不同,但仅在代码中,最好的选择是定义自己的扩展 Array 的类(即,使其成为包装并委托给常规Array的容器类,或者如果您觉得必须,也可以将其委托为子类)。

我想要实现的是,文件 check.rb 中的每个数组都可以 通过parse_test方法调用。

您只需要知道如何创建数组:

module TestParser
  class Array
    def parse_test
      puts 'hello'
    end
  end
end
class Check 
  include TestParser
  Array.new.parse_test
  def do_stuff
    Array.new.parse_test
  end
end
Check.new.do_stuff
Check::Array.new.parse_test
--output:--
hello
hello
hello

当然,TestParser::Array 类没有在 Array 类中找到的任何方法:

module TestParser
  class Array
    def parse_test
      puts 'hello'
    end
  end
end
TestParser::Array.new.parse_test
TestParser::Array.new.size
--output:--
hello
1.rb:11:in `<main>': undefined method `size' for #<TestParser::Array:0x00000101141700> (NoMethodError)

这是因为您在命名空间 TestParser(测试解析器)中创建了一个新的 Array 类 - 您没有重新打开 ruby 内置的 Array 类。

然后当你写include TestParser时,这相当于这样做:

class AnonymousClass
  class Array
    def parse_test
      puts 'hello'
    end
  end
end
class Check  < AnonymousClass 
  Array.new.parse_test
end

当在 Check 中找不到常量时,Ruby 会在继承链中向上寻找常量:

class Parent
  CONST = 10
end
class Child < Parent
  puts CONST
end
--output:--
10
由于内置的 Array 类

是位于继承链最顶端的常量,因此 AnonymousClass 中的Array常量隐藏了 Array 类中内置的 Ruby。 要引用 Array 类中内置的 ruby,您必须编写::Array

module TestParser
  class Array
    def parse_test
      puts 'hello'
    end
  end
end
class Check 
  include TestParser
  p Array
  p ::Array
end
--output:--
TestParser::Array
Array

对于政变*:

module TestParser
  class Array
    def parse_test
      puts 'hello'
    end
  end
end

class Check 
  include TestParser
end
puts TestParser::Array.object_id
puts Check::Array.object_id
--output:--
2152779400
2152779400

*政变恩典:结束重伤者或动物痛苦的致命一击

最新更新