如何访问私有方法

时间:2015-12-20 09:45:56

标签: ruby

我的理解是SELECT capital, name FROM world WHERE capital LIKE CONCAT('%', name, '%'); 意味着对一个实例是私有的。使用显式接收器无法调用私有方法,甚至private。要调用私有方法,我必须完成以下过程:

self

这将调用私有class Sample def foo baz end private def baz end end Sample.new.foo 方法。有没有办法用显式接收器直接调用私有方法?

4 个答案:

答案 0 :(得分:19)

是的,这可以通过Kernel#send

实现
receiver.send :method_name, parameters

虽然有BasicObject#instance_evalKernel#binding操作等变通方法,但调用私有方法的常用方法是在接收方上调用send

答案 1 :(得分:2)

使用BasicObject#instance_eval,您可以调用私有方法。

class Sample
  private
  def baz
    'baz called'
  end
end

Sample.new.instance_eval('baz')
# => 'baz called'
Sample.new.instance_eval { baz }
# => 'baz called'

答案 2 :(得分:1)

如其他答案所示,您可以使用send来调用私有方法。但是,这可能会产生一些不整洁的代码。

如果您确实需要在类的实例上公开访问您的方法,则可以重置方法的可见性。假设您的代码中未定义类,只需重新打开它并设置方法的可见性:

class Sample
  public :baz
end

现在你可以打电话给它:

s = Sample.new
s.baz
# => 'baz called'

答案 3 :(得分:1)

您可以在两个级别上回答您的问题:基本语言级别和反思元级别。

在基础语言层面,如果您只是将隐私的定义与您的问题进行对比,答案就显而易见了:

  

私有方法只能在没有显式接收器的情况下调用

  

我可以在没有明确接收者的情况下呼叫私人吗?

答案显然是“不”,两句话直接相互矛盾。

然而,在反思元层面,答案是“是”。实际上,您可以在元级别上执行几乎任何操作,并绕过几乎任何类型的访问限制,保护,隐藏和封装。

var haystack="UGDVWUDDPRQLUZMSZOJPSIKAIHLTONYXAULECXXKWFQOIKELWOHRVRUCXIAASKHMWTMAJEWGEESLWRTQKVHRRCDYXNTLDSUPXMQTQDFAQAPYBGXPOLOCLFQNGNKPKOBHZWHRXAWAWJKMTJSLDLNHMUGVVOPSAMRUJEYUOBPFNEHPZZCLPNZKWMTCXERPZRFKSXVEZTYCXFRHRGEITWHRRYPWSVAYBUHCERJXDCYAVICPTNBGIODLYLMEYLISEYNXNMCDPJJRCTLYNFMJZQNCLAGHUDVLYIGASGXSZYPZKLAWQUDVNTWGFFYFFSMQWUNUPZRJMTHACFELGHDZEJWFDWVPYOZEVEJKQWHQAHOCIYWGVLPSHFESCGEUCJGYLGDWPIWIDWZZXRUFXERABQJOXZALQOCSAYBRHXQQGUDADYSORTYZQPWGMBLNAQOFODSNXSZFURUNPMZGHTAJUJROIGMRKIZHSFUSKIZJJTLGOEEPBMIXISDHOAIFNFEKKSLEXSJLSGLCYYFEQBKIZZTQQXBQZAPXAAIFQEIXELQEZGFEPCKFPGXULLAHXTSRXDEMKFKABUTAABSLNQBNMXNEPODPGAORYJXCHCGKECLJVRBPRLHORREEIZOBSHDSCETTTNFTSMQPQIJBLKNZDMXOTRBNMTKHHCZQQMSLOAXJQKRHDGZVGITHYGVDXRTVBJEAHYBYRYKJAVXPOKHFFMEPHAGFOOPFNKQAUGYLVPWUJUPCUGGIXGR"; var needle="ABCD"; var size=haystack.length; var candidate_substring=""; var minimal_length=size; var solutions=new Array(); var points=Array(); for(var i=0;i<size;i++){ if(needle.indexOf(haystack[i])>-1) points.push(i); } var limit_i= points.length-4; var limit_k= points.length; for (var i=0;i<limit_i;i++){ for(var k=i;k<limit_k;k++){ if(points[k]-points[i]+1<=minimal_length){ candidate_substring=haystack.substr(points[i],points[k]-points[i]+1); if(is_valid(candidate_substring)){ solutions.push(candidate_substring); if(candidate_substring.length < minimal_length) minimal_length=candidate_substring.length; } } } } document.write('<p>Solution length:'+minimal_length+'<p>'); for(var i=0;i<solutions.length;i++){ if(solutions[i].length<=minimal_length) document.write('<p>Solution:'+solutions[i]+'<p>'); } function is_valid(candidate_substring){ //verify we've got all characters for(var j=0;j<candidate_substring.length;j++){ if(candidate_substring.indexOf(needle.charAt(j))<0) return false; } //...and verify we have two "A" if(candidate_substring.indexOf("A")==candidate_substring.lastIndexOf("A")) return false; return true; },其主要目的是允许您调用一个在运行时之前不知道其名称的方法,还具有绕过访问限制的额外副作用,例如Object#send和{{ 1}}。 (它也忽略了Refinements,这是你应该注意的重要限制!)