Ruby类用静态方法调用私有方法?

时间:2015-04-20 00:16:15

标签: ruby static encapsulation

我有一个包含许多静态方法的类。每个人都必须调用一种常用方法,但我试图不公开后一种方法。将其设为私有只允许从类的自己的实例访问?受保护似乎不会解决这里的问题。

如何隐藏do_calc在静态上下文中被外部调用? (让它可以从前两个静态方法中调用。)

class Foo
  def self.bar
    do_calc()
  end
  def self.baz
    do_calc()
  end
  def self.do_calc
  end
end

3 个答案:

答案 0 :(得分:43)

首先,static并不是 Ruby术语的一部分。

我们举一个简单的例子:

class Bar
  def self.foo
  end
end

它在显式对象foo上定义方法self,该范围在该范围内返回包含的类Bar。 是的,它可以定义为类方法,但 static 在Ruby中没有用。

然后private不起作用,因为在显式对象上定义方法(例如def self.foo)会绕过访问限定符并使方法公开。

您可以做的是使用class << self语法打开包含类的元类,并将那里的方法定义为实例方法:

class Foo
  class << self

    def bar
      do_calc
    end

    def baz
      do_calc
    end

    private

    def do_calc
      puts "calculating..."
    end
  end
end

这将为您提供所需:

Foo.bar
calculating...

Foo.baz
calculating...

Foo.do_calc
NoMethodError: private method `do_calc' called for Foo:Class

答案 1 :(得分:13)

您可以使用private_class_method定义私有类方法,如下所示:

class Foo
  def self.bar
    do_calc
  end

  def self.baz
    do_calc
  end

  def self.do_calc
    #...
  end
  private_class_method :do_calc
end

答案 2 :(得分:1)

或者从Ruby 2.1开始:

public class PatternMatcher
{
  public delegate bool StrictMatchPatternDelegate(string expression, string name);
  public StrictMatchPatternDelegate StrictMatchPattern;
  public PatternMatcher()
  {
    Type patternMatcherType = typeof(FileSystemWatcher).Assembly.GetType("System.IO.PatternMatcher");
    MethodInfo patternMatchMethod = patternMatcherType.GetMethod("StrictMatchPattern", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
    StrictMatchPattern = (expression, name) => (bool)patternMatchMethod.Invoke(null, new object[] { expression, name });
  }
}

void Main()
{
  PatternMatcher patternMatcher = new PatternMatcher();
  Console.WriteLine(patternMatcher.StrictMatchPattern("*.txt", "test.txt")); //displays true
  Console.WriteLine(patternMatcher.StrictMatchPattern("*.doc", "test.txt")); //displays false
}