Saltar al contenido

¿Por qué Ruby tiene métodos privados y protegidos?

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 llamar self.some_private_method; debes llamar private_method con self 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 que self.)

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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *