metodos - manejo de objetos en ruby
¿Hay alguna manera de llamar a un método de Clase privado desde una instancia en Ruby? (6)
A menos que sea un malentendido, ¿no necesitas algo como esto?
class Foo
private
def Foo.bar
# Complex logic goes here
puts "hi"
end
public
def bar
Foo.bar
end
end
Por supuesto, podría cambiar la segunda definición para usar su enfoque self.class.send si desea evitar la codificación física del nombre de la clase ...
Aparte de self.class.send :method, args...
, por supuesto. Me gustaría poner a disposición un método bastante complejo tanto a nivel de clase como de instancia sin duplicar el código.
ACTUALIZAR:
@ Jonathan Branam: esa era mi suposición, pero quería asegurarme de que nadie más hubiera encontrado una forma de evitarlo. La visibilidad en Ruby es muy diferente de la de Java. También tienes razón en que el private
no funciona en los métodos de clase, aunque esto declarará un método de clase privado:
class Foo
class <<self
private
def bar
puts ''bar''
end
end
end
Foo.bar
# => NoMethodError: private method ''bar'' called for Foo:Class
Aquí hay un fragmento de código para acompañar la pregunta. El uso de "privado" en una definición de clase no se aplica a los métodos de clase. Necesita usar "private_class_method" como en el siguiente ejemplo.
class Foo
def self.private_bar
# Complex logic goes here
puts "hi"
end
private_class_method :private_bar
class <<self
private
def another_private_bar
puts "bar"
end
end
public
def instance_bar
self.class.private_bar
end
def instance_bar2
self.class.another_private_bar
end
end
f=Foo.new
f=instance_bar # NoMethodError: private method `private_bar'' called for Foo:Class
f=instance_bar2 # NoMethodError: private method `another_private_bar'' called for Foo:Class
No veo una manera de evitar esto. La documentación dice que no puede especificar la recepción de un método privado. Además, solo puedes acceder a un método privado desde la misma instancia. La clase Foo es un objeto diferente de una instancia determinada de Foo.
No tomes mi respuesta como definitiva. Definitivamente no soy un experto, pero quería proporcionar un fragmento de código para que otros que intenten responder tengan métodos de clase propiamente privados.
Esta es la forma de jugar con métodos de clase privada "reales".
class Foo
def self.private_bar
# Complex logic goes here
puts "hi"
end
private_class_method :private_bar
class <<self
private
def another_private_bar
puts "bar"
end
end
public
def instance_bar
self.class.private_bar
end
def instance_bar2
self.class.another_private_bar
end
def calling_private_method
Foo.send :another_private_bar
self.class.send :private_bar
end
end
f=Foo.new
f.send :calling_private_method
# "bar"
# "hi"
Foo.send :another_private_bar
# "bar"
aclamaciones
Hoy en día ya no necesitas los métodos de ayuda. Simplemente puede alinearlos con la definición de su método. Esto debería ser muy familiar para la gente de Java:
class MyClass
private_class_method def self.my_private_method
puts "private class method"
end
private def my_private_method
puts "private instance method"
end
end
Y no, no puedes llamar a un método de clase privado desde un método de instancia. Sin embargo, en su lugar, podría implementar el método de clase privada como método de clase pública en una clase anidada privada , utilizando el método de ayuda private_constant
. Vea este blogpost para más detalles.
Permítanme contribuir a esta lista de soluciones más o menos extrañas y no soluciones:
puts RUBY_VERSION # => 2.1.2
class C
class << self
private def foo
''Je suis foo''
end
end
private define_method :foo, &method(:foo)
def bar
foo
end
end
puts C.new.bar # => Je suis foo
puts C.new.foo # => NoMethodError
Si su método no es más que una función de utilidad (es decir, no depende de variables de instancia), puede poner el método en un módulo e include
y extend
la clase para que esté disponible tanto como un método de clase privada como privado método de instancia.