ruby - ¿Cuáles son las diferencias entre "privado", "público" y "métodos protegidos"?
access-specifier public-method (7)
Estoy aprendiendo Ruby, y he llegado a un punto en el que estoy confundido.
El libro que estoy usando habla de protected methods
private
, public
y protected methods
, pero todavía estoy un poco confundido. ¿Cuáles son las diferencias entre cada uno?
Al estudiar la información que he tomado de here , extendí las explicaciones a través de errores, y para mi opinión, ayuda a entender por qué y cómo usar protegido y no privado.
1) Protegido:
La línea num 12 falla porque el parámetro recibido es de otra clase, el mensaje de error es claro:
v.rb:12:in `=='': undefined method `sku'' for "Object of another class ==> crash":String (NoMethodError)
2) Privado:
Si se elimina de la línea 8 y 12, y cambio protegido para privado , crash porque en la línea 12, otro no sabe qué es sku :
v.rb:12:in `=='': private method `sku'' called for #<Product:0x00000001574e68 @name="Bread", @quantity=1> (NoMethodError)
El programa:
class Product
attr_accessor :name, :quantity
def initialize(name)
@name = name
@quantity = 1
puts "The SKU is #{self.sku}"
end
def == (other)
self.sku == other.sku
end
protected
def sku
name.crypt("yo")
end
end
milk1 = Product.new("Milk")
milk2 = Product.new("Milk")
bread = Product.new("Bread")
puts milk1 == bread
puts milk1 == milk2
puts milk1 == "Object of another class ==> crash"
Consulte " Ruby Programming / Syntax / Classes " para obtener un ejemplo detallado y una explicación.
En pocas palabras, las diferencias entre private
métodos private
, public
y protected
son la visibilidad de ese método en el programa, algo así como de solo lectura, lectura y escritura, y casi invisible.
A diferencia de algunos de los otros idiomas, no puede ocultar por completo un método privado de Ruby, solo puede acceder a métodos privados para su instancia de objeto y no a ninguna otra instancia de objeto de una clase.
Público, por supuesto, es la accesibilidad total y los métodos suelen ser predeterminados para el público con algunas excepciones.
Los métodos protegidos son accesibles desde objetos de la misma clase o incluso niños, lo que no es el caso de un método privado.
Creo que analizar un receptor explícito es lo importante si tienes problemas para captar el concepto.
Un receptor explícito es un objeto que está aceptando un mensaje.
person.get_name
persona es el receptor y el método "get_name" está dando instrucciones al objeto "persona" para realizar el método "get_name".
class Person
attr_accessor :first_name, :last_name
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
puts "And #{phone_number}" # Private method called when initialized
end
private
def phone_number
return "XXX-XXX-XXXX"
end
end
p p1 = Person.new("mike", "jones")
p p1.phone_number # Not within the context of the object instance.
Cuando un método es privado, solo puede ser utilizado por otros métodos dentro del objeto en cuya clase está definido.
La diferencia estará en Visibilidad y cómo se ven afectados por la herencia :
Visibilidad :
|| En cualquier lugar || Se puede acceder al público desde dentro y fuera de la clase.
|| Dentro de la clase || Tanto Privado como Protegido solo se puede acceder desde dentro de la clase.
La similitud entre Protegido y Privado:
- Se puede acceder a ambos desde fuera de la clase a través de un método público.
Las diferencias entre Protegido y Privado son:
El método privado no se puede llamar con un receptor (ni siquiera con #self). A MENOS QUE ... llamando a un método PRIVATE SETTER . Si intentas eliminar el receptor, Ruby creará una variable local. El yo es imprescindible en este caso.
Protected puede o no usar self.
Protected puede acceder al método protegido de otro objeto que proviene de la misma clase, Private can not.
Cuando se trata de herencia :
Los métodos privados solo se pueden invocar en subclases implícitamente (simplemente el nombre del método) pero no explícitamente (usando #self).
Protected se puede llamar en ambos sentidos (con o sin #self || implícita o explícitamente).
Ejemplo con el siguiente código:
class Foo
private
def pri
''hey I am private of Foo''
end
protected
def prot
''Hey I am protected of Foo''
end
end
Permítanme explicar Private
métodos Private
y protected
funcionan de manera diferente en Ruby
que en la mayoría de los otros lenguajes de programación. Supongamos que tiene una clase llamada Foo
y una subclase SubFoo
. En idiomas como Java
, SubFoo
no tiene acceso a ningún método privado definido por Foo. Como se ve en la Solución, Ruby no ofrece forma de ocultar los métodos de una clase de sus subclases. De esta manera, las obras privadas de Ruby
como las de Java
protected
.
Supongamos además que tiene dos instancias de la clase Foo, a
y b
. En idiomas como Java
, a
y b
pueden llamar a private methods
los demás. En Ruby
, necesitas usar un protected method
para eso. Esta es la principal diferencia entre private
métodos private
y protected
en Ruby
.
class SubFoo < Foo
def call_pri_of_foo
pri
end
def call_prot_of_foo
prot
end
end
Ahora subclase de Foo
> sub_foo = SubFoo.new
=> #<SubFoo:0x00000002b56ad8>
> sub_foo.call_pri_of_foo
=> "hey I am private of Foo"
> sub_foo.call_prot_of_foo
=> "Hey I am protected of Foo"
Ahora llamando a los accesorios dentro de SubFoo
next_sub_foo = SubFoo.new
=> #<SubFoo:0x00000002b1a0b0>
def next_sub_foo.access_private(child_of_sub_foo)
child_of_sub_foo.pri
end
def next_sub_foo.access_protected(child_of_sub_foo)
child_of_sub_foo.prot
end
Hasta aquí; parece que no hay diferencia
> next_sub_foo.access_private(sub_foo)
# => NoMethodError: private method `pri'' called for #<SubFoo:0x00000002b56ad8>
Ahora llamando al accessor
> next_sub_foo.access_protected(sub_foo)
# => "Hey I am protected of Foo"
pero puede acceder a los métodos protegidos de sus hermanos
class Dog
attr_accessor :name, :age
def initialize(n, a)
self.name = n
self.age = a
end
def accessing_private
"#{self.name} in human years is #{human_years}. This is secret!"
end
def accessing_protected
"Will this work? " + a_protected_method
end
def eat_more_than(other)
# accessing other instance''s protected method from the same class
daily_diet < other.daily_diet
"#{name} eats more than #{other.name}"
end
def boy
gender_method("boy") # accessing private setter method
end
protected
def daily_diet
age * 2 # the younger, the more they have to eat
end
def a_protected_method
"Yes, I''m protected!"
end
private
attr_writer :gender
def gender_method(gender)
self.gender = gender # private setter method requires self
"#{name} is a #{gender}"
end
def human_years
age * 8
end
end
# Create the first object of Dog
blake = Dog.new("Blake", 5)
p blake.accessing_private # "Blake in human years is 16. This is secret!"
p blake.accessing_protected # "Will this work? Yes, I''m protected!"
# Create the second object of Dog
jackson = Dog.new("Jackson", 1)
# Below, protected methods from different objects of the same type/class
# are proven to share access
p jackson.eat_more_than(blake) # true -> "Jackson eats more than Blake"
# Below, accessing private setter method through a public method.
p blake.boy # Blake is a boy
También puede ver el blog de @tenderlove
para obtener una imagen más clara http://tenderlovemaking.com/2012/09/07/protected-methods-and-ruby-2-0.html
public
métodos public
están abiertos a todos. En cuanto a private
versus protected
, me refiero a " Métodos privados de Ruby vs. Métodos protegidos ":
¿Cuál es la diferencia entre los métodos "privados" y "protegidos" en Ruby? En Ruby, la principal diferencia entre un método ''privado'' y ''protegido'' es que no se puede llamar a un método privado con un receptor explícito, mientras que un método protegido puede hacerlo. ¿Qué es un "receptor explícito", preguntas? Un receptor explícito es el objeto que está recibiendo un mensaje. En el siguiente ejemplo, tenemos un receptor (''parent'') y un método (''get_name''). El objeto ''padre'' está recibiendo las instrucciones para realizar el método ''get_name''.
Público : se puede llamar desde cualquier lugar
Privado : el método no se puede llamar fuera del alcance de la clase. El objeto solo puede enviarse el mensaje
por ejemplo: el panadero tiene el método de bake
como público pero break_eggs
es privado
Protegido : puede llamar a los métodos protegidos de un objeto, siempre que el objeto predeterminado sea una instancia de la misma clase que el objeto cuyo método está llamando.
ej .: con n
método protegido, c1
puede solicitar a c2
que ejecute c2.n
, porque c1
y c2
son instancias de la misma clase
Y por último pero no menos importante:
- Herencia : las subclases heredan las reglas de acceso a los métodos de su superclase
si es "clase D <C", entonces D exhibirá el mismo comportamiento de acceso que las instancias de C
referencia: http://www.amazon.com/Ruby-Rails-Techniques-Developers/dp/1932394699