0
class Check 
  include TestParser
  # so on
end

和模块结构:

module TestParser
  class Array
    def parse_test
      # method
    end
  end
end

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

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

4

3 回答 3

4

您正在寻找的是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

但是,我强烈反对做这些事情中的任何一个。最好做一个封装了 Array 并且只提供你需要的方法的对象:

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::Array只有一个方法的类(parse_test)。由于TestParser没有方法,将其包含到另一个模块/类中对可用的方法没有影响。包括TestParser不做任何事情TestParser::Array

于 2013-09-10T01:17:32.433 回答
1

您已经定义了一个TestParser::Array包含该parse_test方法的新类;你还没有修改Array类。

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

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

class Array  
  def parse_test
    # method
  end
end

但这会修改Array​​你说你不想做的基类。此外,一旦文件为 required,它将立即进行修改。不需要包含。

在当前实验性的 Ruby 2.0 特性(称为细化)之外,没有办法将这些类型的修改本地化到基类(称为“猴子补丁”)。

如果您希望数组的行为不同但仅在您的代码中,您最好的办法是定义您自己的扩展 Array 的类(也就是说,使其成为一个容器类包装并委托给一个常规的Array,或者如果您觉得必须是一个子类) .

于 2013-09-10T01:15:38.400 回答
-1

我想要实现的是文件 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 类是位于继承链最顶端的Array常量,所以 AnonymousClass 中的常量隐藏了 Ruby 内置的 Array 类。要引用 Ruby 内置的 Array 类,您必须编写::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

*致命一击:结束重伤人员或动物痛苦的致命一击

于 2013-09-10T05:13:48.660 回答