2010-05-20 15 views
32

En Ruby, ¿cómo se crea una constante de clase privada? (es decir, uno que es visible dentro de la clase, pero no en el exterior)Cómo puedo hacer constantes de clases privadas en Ruby

class Person 
    SECRET='xxx' # How to make class private?? 

    def show_secret 
    puts "Secret: #{SECRET}" 
    end 
end 

Person.new.show_secret 
puts Person::SECRET # I'd like this to fail 
+1

Por supuesto, "privado" en Ruby no significa lo que significa en la mayoría de los idiomas . Ruby no es tan grande en la clandestinidad, así que si quieres acceder a algo, siempre puedes (pero tal vez no con la sintaxis más obvia). Ruby's 'private' solo dice que no puede ir precedido de un punto (' .') (que supongo que también es una pista de por qué no funcionará en '::') – Amadan

+2

Por las dudas. Ruby 1.9.3 tiene ahora constantes privadas. – whitequark

Respuesta

12

También puede cambiar su constante en un método de clase:

def self.secret 
    'xxx' 
end 

private_class_method :secret 

Esto lo hace accesible en todas las instancias de la clase, pero no en el exterior.

+0

Tal vez un poco de meta-programación haría esto más aceptable. – DMisener

+0

Lo pensé un poco más y luego me di cuenta de que el enfoque anterior no hace que la constante esté disponible para los métodos de instancia, así que creo que me quedaré con el enfoque @@ var. – DMisener

+0

@DMisener: Ruby tiene un método para las constantes faltantes, si alguien quiere magia de meta-programación. –

9

En lugar de una constante se puede utilizar un @@ class_variable, que siempre es privada.

class Person 
    @@secret='xxx' # How to make class private?? 

    def show_secret 
    puts "Secret: #{@@secret}" 
    end 
end 
Person.new.show_secret 
puts Person::@@secret 
# doesn't work 
puts Person.class_variable_get(:@@secret) 
# This does work, but there's always a way to circumvent privateness in ruby 

Por supuesto, entonces el rubí no hará nada para hacer cumplir la constantness de @@ secreto, pero rubí hace muy poco para hacer cumplir constantness para empezar, así que ...

+0

Gracias ... Parece obvio en retrospectiva. – DMisener

1

Bueno ...

@@secret = 'xxx'.freeze 

tipo de obras.

131

A partir del rubí 1.9.3, que tienen el método Module#private_constant, que parece ser exactamente lo que quería:

class Person 
    SECRET='xxx'.freeze 
    private_constant :SECRET 

    def show_secret 
    puts "Secret: #{SECRET}" 
    end 
end 

Person.new.show_secret 
# => "Secret: xxx" 

puts Person::SECRET 
# NameError: private constant Person::SECRET referenced 
+5

Esta es la respuesta correcta, en mi humilde opinión. –

+1

Esto es tan increíble. No tenía idea de si esto era siquiera una cosa. –

+0

No veo este método en la API 'Module' hasta http://www.ruby-doc.org/core-2.0.0/Module.html (http://www.ruby-doc.org/core -1.9.3/Module.html) –

Cuestiones relacionadas