This principle applies generally to the syntax of object-oriented programming languages. In simpler form, it states that there should be no difference between working with an attribute, precomputed property, or method/query:
[~/srcDaveThomasProgrammingRuby]$ cat virtual_attributes.rb
class BookInStock
attr_reader :isbn
attr_accessor :price
def initialize(isbn, price)
@isbn = isbn
@price = Float(price)
end
def price_in_cents
Integer(price*100 + 0.5)
end
# ...
end
book = BookInStock.new("isbn1", 33.80)
puts "Price = #{book.price}"
puts "Price in cents = #{book.price_in_cents}"
Here we’ve used attribute methods to create a virtual instance
variable. To the outside world, price_in_cents seems to be an
attribute like any other. Internally, though, it has no corresponding instance variable.
[~/srcDaveThomasProgrammingRuby]$ ruby virtual_attributes.rb Price = 33.8 Price in cents = 3380
public a menos que sean explícitamente declarados como private o protected.
initialize que es implícitamente privado.
[~/rubytesting]$ cat privado_main2.rb
require 'pry'
def tutu
"tut "
end
class Titi
def toto
tutu()
end
end
binding.pry()
[~/rubytesting]$ ruby privado_main2.rb
From: /Users/casiano/local/src/ruby/rubytesting/privado_main2.rb @ line 15 :
10: end
11: end
12:
13: binding.pry()
14:
=> 15: z = Titi.new
16: puts z.toto()
[1] pry(main)> self
=> main
[2] pry(main)> self.class
=> Object
[4] pry(main)> self.private_methods(false).select {|x| x =~ /tut/ }
=> [:tutu]
[5] pry(main)> self.tutu
NoMethodError: private method `tutu' called for main:Object
from (pry):5:in `<main>'
[6] pry(main)> tutu
=> "tut "
[7] pry(main)> Titi.new.tutu
NoMethodError: private method `tutu' called for #<Titi:0x007ff03612e700>
from (pry):7:in `<main>'
[8] pry(main)> Titi.new.toto
=> "tut "
[9] pry(main)>
m es un método privado, deberá ser invocado implícitamente en self,
esto es, como función, m(),
y no con receptor explícito: (obj.m o bien self.m).
self
y no debe ser invocado explícitamente en un objeto
private
protected
pueden ser invocados desde la clase o sus subclases
protected
pueden ser invocados en cualquier objeto de la clase
y no requieren la invocación implícita via self
public, private y protected.
Module.
self se refiere a la clase, podemos usar
estos métodos public, private y protected como si de palabras reservadas se tratara.
class Point # public methods go here # The following methods are protected protected # protected methods go here # The following methods are private private # private methods go here end
class Widget
def x # Accessor method for @x
@x
end
protected :x # Make it protected
def utility_method # Define a method
nil
end
private :utility_method # And make it private
end
private_class_method:
private_class_method :new
public_class_method
$ cat -n accesing_private_method.rb
1 class Widget
2 def initialize()
3 @x = 4
4 end
5
6 def x
7 @x
8 end
9 protected :x # Make it protected
10
11 def utility_method # Define a method
12 puts "Inside utility_method"
13 end
14 private :utility_method # And make it private
15 end
16
17 w = Widget.new # Create a Widget
18 w.send :utility_method # Invoke private method!
19 w.instance_eval { utility_method } # Another way to invoke it
20
21 w.instance_eval { puts @x } # Read instance variable of w
Cuando ejecutamos, obtenemos:
[~/point]$ ruby accesing_private_method.rb Inside utility_method Inside utility_method 4
Utilice public_send en vez de send si no se quiere que,
por error, se llame inadvertidamente a un método privado.