def
followed by the method name and the parameter names, and ends with the keyword end
.def test
puts "Hello World"
end
test # Causes "Hello World" to be printed
Note that unlike Java and C#, Ruby does not require the return type or the parameter types to be stated. Every Ruby method returns a value. In the above example,
puts
returns nil, and as this is the last statement in the method test, test will also return nil. The return
keyword is entirely optional (though necessary if you want to jump out of the middle of a method, of course).Visibility
By default, all methods are public; they can be accessed from anywhere by anything.
Private methods can only be accessed from with the class and (unlike Java et al) its subclasses. That said, you can access private methods from anywhere using the send method, or modify their visibility on-the-fly, so it would seem that this is more advisory than anything else; the API writer is telling you that you probably should not use those methods.
The
private
keyword indicates that all subsequent methods (until public or protected is encounted) will be private.class MyClass
def public_method
puts "In public_method"
end
# You can access private methods within the class
def private_via_public_method
puts "private_via_public_method"
private_method
end
private # Flags all subsequent methods
# as private
def private_method
puts "In private_methodstance_method"
end
end
class MySubClass < MyClass
# You can also access private methods
# within any subclass
def private_via_subclass_public_method
puts "private_via_subclass_public_method"
private_method
end
end
mc = MyClass.new
mc.private_via_public_method
mc.public_method
#mc.protected_method # Protected method
# not visible
#mc.private_method # Private method
# not visible
mc.send :private_method # Private method
# accessed with send
# Visibility can be changed dynamically
class MyClass
public :private_method
end
mc.private_method # Private method is
# now visible
The third visibility type is protected, which is a little more esoteric. The protected visibility is very similar to private, except that protected allows you call method from a different object, as long as that object is of the same class or subclass. To put it another way, private is restricted to the specific object, protected is restricted to the class.
class MyClass
# You can access private methods on the
# object within the class
def private_via_public_method
private_method
end
# You can access protected methods on another
# object within the class
def protected_via_other_public_method
mc = MyClass.new
mc.protected_method
end
# This will fail
# You cannot access private methods on another
# object, even within the class
def private_via_other_public_method
mc = MyClass.new
mc.private_method
end
protected
def protected_method
puts "In protected_method"
end
private
def private_method
puts "In private_methodstance_method"
end
end
The important point here is that both private and protected methods can only be used with the class (or subclass), but that private methods are further restricted to calls that do not require the dot operator.
As an aside, in Ruby all constants are public, and all variables are private
Class methods
Class methods are methods that are applied to the class rather than to a specific instance of the class. The most important example of a class method is
new
; in Rails the find
method is also used very frequently.s = String.new "My string" # Equivalent to
# s = "My string"
post = Post.find :first # gets the first record
# from the posts table
As can be seen, class methods are invoked by using the class name, rather than the object, and as in the examples above they are often used to create or retrieve instances of the class.
Class methods are written much like instance methods, but with the keyword
self
before the method name. You cannot call a class method from an instance of the class, or call an instance method from the class itself. This does mean you can have a class method with the same name as an instance method.See the next section for an example of a class method.
The initialize method
I have already mentioned the
new
class method. What this does is create a new instance of the object, and then it invokes the initialize
method, if it exists. The initialize
method is always private; there seems no way to change that. However, you can invoke it from within your class.The following code illustrates the use of
initialize
and class methods.class MyClass
def initialize
puts "In initialize"
end
def self.class_method
puts "In class_method"
end
def instance_method
puts "In instance_method"
end
end
MyClass.class_method # Prints "In class_method"
mc = MyClass.new # Would cause error; cannot call class methods on an object
#mc.class_method # Prints "In initialize"
mc.instance_method # Prints "In instance_method"
Class initialize method?
Sometimes you might want to do something to set up your class. You want it to run before any instances and created. I believe Rails does this for ActiveRecords, inspecting the database to see what fields are present, so it will know how to handle requests, rather than inspecting the database each time a request is made.
There is no method that supports this, you just put your code straight into the class definition.
class MyClass
p 'This will be printed when the class is loaded'
def initialize
p 'This will be printed when an object is instantiated'
end
end
Multiple return results
Pretty much every modern language allows you to send multiple arguments to a function/procedure/method. How many allow you to return multiple arguments? Certainly not the C derivatives, and really I cannot see why that should be so. At the machine code level, I would assume there is no difference. I would guess the reason is that C is based on a mathematical concept of functions, F = f(x,y,z), and Java and C# had followed suit.
Not so Ruby, which allows you to return as many values as you like. Here is a trivial example to illustrate that:
def test
return return 1, 'two', 3
end
a, b = test
p a # => 1
p b # => "two"
a, b, c, d = test
p a # => 1
p b # => "two"
p c # => 3
p d # => 4
Note that in this case the
return
keyword is required. What is actually returned is an array containing each each return value. This can lead to confusion...def tester
return 3, 6
end
def output x, y = nil
p "x=#{x} y=#{y}"
end
x, y = tester
output x, y
# => "x=3 y=6"
output tester
# => "x=36 y="
The first call to tester correctly gets the two values assigned to the two variables. However, the second fails; the array is passed directly to the output method, which has no clue about the context, and just sees an array. What is really happening is a bit of trickery. Ruby does not pass back multiple values at all; it just passes back an array when multiple values are used with return. Meanwhile, at the other end, Ruby allows multiple varaibles to be set from an array.
x, y = [7, 6]
output x, y
Overall we have the illusion of muliple returns.
blog on dynamically creating methods:
http://ola-bini.blogspot.com/2008/05/dynamically-created-methods-in-ruby.html
Struggling with Ruby: Contents Page
No comments:
Post a Comment