Investigamos en diferentes foros y así regalarte la solución a tu dilema, si tienes preguntas déjanos tu pregunta y respondemos porque estamos para ayudarte.
Solución:
protected
Los métodos pueden ser llamados por cualquier instancia de la clase definitoria o sus subclases.
private
los métodos solo se pueden llamar desde dentro del objeto que realiza la llamada. No puede acceder directamente a los métodos privados de otra instancia.
Aquí hay un ejemplo práctico rápido:
def compare_to(x)
self.some_method <=> x.some_method
end
some_method
no puede ser private
aquí. Debe ser protected
porque lo necesita para admitir receptores explícitos. Sus métodos típicos de ayuda interna generalmente pueden ser private
ya que nunca necesitan ser llamados así.
Es importante tener en cuenta que esto es diferente a la forma en que funciona Java o C ++. private
en Ruby es similar a protected
en Java / C ++ en que las subclases tienen acceso al método. En Ruby, no hay forma de restringir el acceso a un método desde sus subclases como puede hacerlo con private
en Java.
La visibilidad en Ruby es en gran medida una “recomendación” de todos modos, ya que siempre puede obtener acceso a un método utilizando send
:
irb(main):001:0> class A
irb(main):002:1> private
irb(main):003:1> def not_so_private_method
irb(main):004:2> puts "Hello World"
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> foo = A.new
=> #
irb(main):009:0> foo.send :not_so_private_method
Hello World
=> nil
La diferencia
- Cualquiera puede llamar a sus métodos públicos.
- Puede llamar a sus métodos protegidos, o otro miembro de su clase (o una clase descendiente) puede llamar a sus métodos protegidos desde el exterior. Nadie más puede.
- Solo usted puede llamar a sus métodos privados, porque solo se pueden llamar con un receptor implícito de
self
. Incluso tú no puedo llamarself.some_private_method
; debes llamarprivate_method
conself
implícito.- iGEL señala: “Sin embargo, hay una excepción. Si tiene un método privado age =, puede (y debe) llamarlo con self para separarlo de las variables locales”.
- Desde Ruby 2.7 el
self
el receptor puede ser explícito,self.some_private_method
esta permitido. (Cualquier otro receptor explícito aún no está permitido, incluso si el valor de tiempo de ejecución es el mismo queself
.)
En Ruby, estas distinciones son solo consejos de un programador a otro. Los métodos no públicos son una forma de decir “Me reservo el derecho de cambiar esto; no dependa de ello”. Pero todavía tienes las afiladas tijeras de send
y puede llamar a cualquier método que desee.
Un breve tutorial
# dwarf.rb
class Dwarf
include Comparable
def initialize(name, age, beard_strength)
@name = name
@age = age
@beard_strength = beard_strength
end
attr_reader :name, :age, :beard_strength
public :name
private :age
protected :beard_strength
# Comparable module will use this comparison method for >, <, ==, etc.
def <=>(other_dwarf)
# One dwarf is allowed to call this method on another
beard_strength <=> other_dwarf.beard_strength
end
def greet
"Lo, I am #name, and have mined these #age years.
My beard is #beard_strength strong!"
end
def blurt
# Not allowed to do this: private methods can't have an explicit receiver
"My age is #self.age!"
end
end
require 'irb'; IRB.start
Entonces puedes correr ruby dwarf.rb
y haz esto:
gloin = Dwarf.new('Gloin', 253, 7)
gimli = Dwarf.new('Gimli', 62, 9)
gloin > gimli # false
gimli > gloin # true
gimli.name # 'Gimli'
gimli.age # NoMethodError: private method `age'
called for #
gimli.beard_strength # NoMethodError: protected method `beard_strength'
called for #
gimli.greet # "Lo, I am Gimli, and have mined these 62 years.
My beard is 9 strong!"
gimli.blurt # private method `age' called for #
Métodos privados en Ruby:
Si un método es privado en Ruby, entonces no puede ser llamado por un receptor explícito (objeto). Solo se puede llamar implícitamente. Puede ser llamado implícitamente por la clase en la que se ha descrito, así como por las subclases de esta clase.
Los siguientes ejemplos lo ilustrarán mejor:
1) Una clase Animal con método privado class_name
class Animal
def intro_animal
class_name
end
private
def class_name
"I am a #self.class"
end
end
En este caso:
n = Animal.new
n.intro_animal #=>I am a Animal
n.class_name #=>error: private method `class_name' called
2) Una subclase de animal llamada anfibio:
class Amphibian < Animal
def intro_amphibian
class_name
end
end
En este caso:
n= Amphibian.new
n.intro_amphibian #=>I am a Amphibian
n.class_name #=>error: private method `class_name' called
Como puede ver, los métodos privados solo se pueden llamar implícitamente. No pueden ser llamados por receptores explícitos. Por la misma razón, los métodos privados no se pueden llamar fuera de la jerarquía de la clase definitoria.
Métodos protegidos en Ruby:
Si un método está protegido en Ruby, tanto la clase definitoria como sus subclases pueden llamarlo implícitamente. Además, también pueden ser llamados por un receptor explícito siempre que el receptor sea uno mismo o de la misma clase que el de uno mismo:
1) Una clase Animal con método protegido protect_me
class Animal
def animal_call
protect_me
end
protected
def protect_me
p "protect_me called from #self.class"
end
end
En este caso:
n= Animal.new
n.animal_call #=> protect_me called from Animal
n.protect_me #=>error: protected method `protect_me' called
2) Una clase de mamíferos que se hereda de la clase de animales.
class Mammal < Animal
def mammal_call
protect_me
end
end
En este caso
n= Mammal.new
n.mammal_call #=> protect_me called from Mammal
3) Una clase de anfibios heredada de la clase Animal (igual que la clase de mamíferos)
class Amphibian < Animal
def amphi_call
Mammal.new.protect_me #Receiver same as self
self.protect_me #Receiver is self
end
end
En este caso
n= Amphibian.new
n.amphi_call #=> protect_me called from Mammal
#=> protect_me called from Amphibian
4) Una clase llamada Árbol
class Tree
def tree_call
Mammal.new.protect_me #Receiver is not same as self
end
end
En este caso:
n= Tree.new
n.tree_call #=>error: protected method `protect_me' called for #
Puedes añadir valor a nuestro contenido informacional cooperando tu veteranía en las ilustraciones.