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 wCuando 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.