名称空间与顶级方法冲突

时间:2016-01-14 13:40:38

标签: ruby

我有以下Ruby命名空间问题:

我在"库"中有许多顶级方法,其中我有一个get_name(param)方法。 问题是我想在具有自己的get_name()方法的类中使用这个get_name(param)方法(没有param!)。 当然这会导致问题,因为2种方法不同,而且班级中的新方法会覆盖顶级方法。

有没有办法做这样的事情:

def get_name(param)
  puts param
end

class Foo 
  def get_name()
    puts "name"
  end
  def bar()
    self.get_name() #should work and print name, i.e. it uses the get_name method of Foo
    get_name("abc") #should work and print abc, i.e. it uses the top-level method
  end
end

我想知道是否有一种简单的方法可以实现这一点,而无需更改顶级方法的名称或范围。 (目标是将这些可用而不作为全局方法进行修改,但仍然能够无错误地调用Foo的实例方法。

3 个答案:

答案 0 :(得分:2)

如果库方法确实是顶级方法,并且不属于任何类或模块,那么它们将被定义为private类的Object方法。

您可以执行以下操作来调用它:

  def bar()
    self.get_name()
    Object.send(:get_name, "abc")  # Will print "abc" to console
  end

答案 1 :(得分:0)

所谓的“顶级方法”只是main对象的一种方法,它只是Object。如果您希望能够(几乎)在任何地方调用该方法,则应将其设为内核方法

module Kernel
  def get_name(param)
    puts param
  end
end

请注意,Kernel几乎位于祖先链的任何类的尾部(BasicObject之前),这意味着几乎所有对象都是Kernel。因此,在Foo课程中,您可以像这样覆盖它:

class Foo
  def get_name(*args)
    return super if args.any?
    puts 'name'
  end
end

修改

如果你不能制作那些顶级方法的内核方法,你可以将main对象存储在常量或全局变量中,并在其上调用那些顶级方法。

$main = self

class Foo
  def get_name(*args)
    return $main.send(:get_name, *args) if args.any?
    puts 'name' 
  end
end

答案 2 :(得分:0)

首先:没有“顶级方法”这样的东西。 Ruby中只有一种方法:实例方法。

您指的方法是private Object实例方法。由于Object是几乎所有其他类的超类(不包括Object及其超类),如果您确定在继承层次结构中的其他位置没有其他同名的方法,则可以使用Method#super_method访问该方法然后调用它:

def get_name(param)
  puts param
end

class Foo 
  def get_name
    puts 'name'
  end

  def bar
    get_name #should work and print name, i.e. it uses the get_name method of Foo
    method(:get_name).super_method.('abc') #should work and print abc, i.e. it uses the top-level method
  end
end

Foo.new.bar
# name
# abc

或者,如果知道继承层次结构中是否存在同名的其他方法,则可以获取对{{1直接来自UnboundMethod然后Objectbind

call