2015-01-09 38 views
3

鉴于红宝石一类:如何访问Ruby中的私有类方法?

class MyClass 
    def self.my_class_method 
    puts "class method" 
    end 

    private 

    def my_method 
    puts "regular method" 
    end 

    private_class_method :my_class_method 
end 

要访问私有方法我可以调用类对象.send(:my_method),但如何做类方法的工作?

回答

9

你应该这样做:

class MyClass 
    def self.my_class_method 
    puts "class method" 
    end 

    private 

    def my_method 
    puts "regular method" 
    end 

    private_class_method :my_class_method 
end 

# to call class method 
MyClass.send :my_class_method # => class method 
# to call instance method 
MyClass.new.send :my_method # => regular method 

在Ruby中,类(S)也是对象,所以你也可以拨打#send方法的类。

在Ruby中,你可以定义私有类方法作为

class MyClass 
    class << self 
    private 

    def my_class_method 
     puts "class method" 
    end 
    end 
end 

或者使用thhis 宏观类似方法:private_class_method

+0

谢谢你的提示! – Severin

1

仅供参考,这不是你如何创建一个私有的类方法。

class A 
    private 

    def self.foo 
    "foo" 
    end 
end 

A.foo # => "foo" 

要创建私有类方法,您需要使用private_class_method

class A 
    def self.foo 
    "foo" 
    end 

    private_class_method :foo 
end 

A.foo # => private method `foo' called for A:Class 
+0

谢谢,我没有注意到..现在我补充说。但这不是问题。 –

+0

谢谢指出!相应地更新了问题。 – Severin

1

首先,MyClass.send(:my_method)不起作用。您必须将其发送到实例:MyClass.new.send(:my_method)

然后,你的my_class_method是不是真的私人。
Ruby的语义private与您在其他语言中可能会使用的有所不同。由于Ruby允许您选择跳过封装,因此private仅意味着只能在不向实际对象发送消息的情况下隐式调用

例如:

class Example 
    def test 
    'foobar' 
    end 

    def hello 
    puts test  # implicit receiver 
    puts self.test # explicit receiver 
    end 
end 

这一切都不错,但为什么是你的问题很重要?
因为您在self上明确声明my_class_method。这样做绕过private修饰符,并且该方法是公开的。这意味着,你可以把它用:

MyClass.my_class_method 

如果你真的需要private类的方法,那么你可以将它们定义在元类:

class MyClass 

    class << self 

    private 

    def my_class_method 
     puts "class method" 
    end 
    end 


    private 

    def my_method 
    puts "regular method" 
    end 

end 

这将使my_class_method实际上私人,并迫使你用以下任何一种方式调用它:

MyClass.send :my_class_method 
MyClass.class_exec { my_class_method } 
MyClass.class_eval { my_class_method } 
MyClass.class_eval "my_class_method" 
2

没有类方法这样的事情。类方法只是该类的单例方法。但是没有单身方法这样的事情。单例方法只是单例类的实例方法。所以,类方法只是类的单例类的实例方法。

因为有作为一类方法没有这样的事情,只有实例方法,你已经知道该怎么做:

访问私有方法,我可以在类对象调用.send(:my_method),但是这是如何工作的对于类方法?