如何使用继承类获取文件名?

时间:2014-02-18 17:11:32

标签: ruby inheritance

我想获取带有继承函数的ruby类的文件名。这样的事情:

# a.rb
class A
  def get_file()
    __FILE__
  end
end

# b.rb
class B < A
end

# c.rb
myobj = B.new()
puts myobj.get_file()

b.rb是预期的,但我有a.rb。

我有很多像B这样的类,所以我不想为继承了A的每个类添加一个函数。我想在A类中添加一个泛型方法来获取好的文件。 有人可以帮帮我吗?

埃里克

2 个答案:

答案 0 :(得分:1)

这就是我的目录:

-home
  |-kirti
     |-workpspace
         |-Ruby
            |- a.rb
            |- b.rb
            |- c.rb

以下是文件内容:

<强> a.rb

class A
  def get_file()
    [__FILE__,$0]
  end
end

<强> b.rb

require_relative 'a.rb'

class B < A
end

<强> c.rb

require_relative 'b.rb'

myobj = B.new()
puts myobj.get_file()

现在我正在运行代码:

(arup~>Ruby)$ ruby c.rb
/home/kirti/workspace/Ruby/a.rb
c.rb
(arup~>Ruby)$ 

现在让我首先提出__FILE__

的文档
  

当前正在执行的文件的名称,包括相对于启动应用程序的目录的路径(或当前目录,如果已更改)。 当前文件在某些情况下与正在运行的应用程序的启动文件不同,后者在全局变量$0中可用。< / em>的

从文档中可以清楚地看出__FILE__是当前文件位置,它与启动文件$0不同。所以 c.rb 是您的启动文件,但当前文件是 /home/kirti/workspace/Ruby/a.rb

基本上,魔术变量__FILE__的值是在加载文件时创建和存储(但从未更新)的相对路径。现在,在您的情况下,您将其保存在文件a.rb内,因此它包含 /home/kirti/workspace/Ruby/a.rb

class B < A ;end,表示您要将A添加到类B的祖先链中。这并不意味着将A中的方法添加到Bget_file方法仍在cass A中。您的对象myobj将首先在类get_file内搜索方法B,如果未找到,则将其搜索到祖先链中的类和模块中。现在get_file位于班级A内,A位于文件a.rb中,因此__FILE__的值应设置为 { {1}} ,第一次加载 a.rb 时。现在/home/kirti/workspace/Ruby/a.rb将课程require_relative 'a.rb'提供给文件 b.rb ,但A的值不会更新。

希望有所帮助!

答案 1 :(得分:-2)

感谢Arup和Jesse帮助我。我已经找到了他们的响应解决方案。

这是我的解决方案:

<强> a.rb

class A
  # Called from b.rb at `class A < B`. `subclass` is the Class object B.
  # This method makes sure every subclass (class B, class C...)
  # has #get_file defined correctly for instances of the subclass.
  def self.inherited (subclass)
    subclass.instance_eval do
      # This array contains strings like "/path/to/a.rb:3:in `instance_eval'".
      strings_ary = caller

      # We look for the first string containing "(root)".
      require_index = strings_ary.index {|x| x.include?("(root)") }
      require_string = strings_ary[require_index]
      # We use a regex to extract the filepath from require_string.
      filepath = require_string[/^(.*):\d+:in `\(root\)'/, 1]
      # This defines the method #get_file for instances of `subclass`.
      define_method(:get_file) { filepath }
    end
  end

  # For instances of class A only, we use the __FILE__ keyword.
  # This method is overwritten by the #get_file method defined above.
  def get_file
    __FILE__
  end
end

<强> b.rb

class B < A
end

<强> c.rb

require_relative 'a'
require_relative 'b'

p A.new.get_file
p B.new.get_file

c.rb的输出

"<path>/Test/lib/tmp/a.rb"
"<path>/Test/lib/tmp/b.rb"

@Jesse =&gt;我不知道为什么你的解决方案在我的桌面上不起作用。关键字 top(required)不存在,我已将(root)替换为索引搜索而不是rindex。我在ruby 1.7.3上。我的来电者的输出是:

<path>/Test/lib/tmp/a.rb:6:in `instance_eval'
<path>/Test/lib/tmp/a.rb:6:in `inherited'
<path>/Test/lib/tmp/b.rb:4:in `(root)'
<path>/jruby-1.7.3/lib/ruby/shared/rubygems/custom_require.rb:1:in `require'
<path>/jruby-1.7.3/lib/ruby/shared/rubygems/custom_require.rb:1:in `(root)'
<path>/jruby-1.7.3/lib/ruby/shared/rubygems/custom_require.rb:36:in `require'
<path>\Test\lib\tmp\c.rb:5:in `(root)'

再次感谢您的帮助。

埃里克