my_object.class
, which returns an object of the Class
class.10.class # => Fixnum
10.class.class # => Class
"Hello World".class # => String
If you do not have an instance of a class, you can determine the name of the class using the
inspect
method (this might be useful if you are in a class method in a super class and want to know the subclass).The
superclass
method will produce the superclass.10.class.superclass # => Integer
10.class.superclass.superclass # => Numeric
10.class.superclass.superclass.superclass # => Object
As in Java, everything inherits from
Object
.You can check if an object is of a certain class using the
is_a?
method. This will return true
if the object is of the given class or of a subclass of it."Hello World".is_a? String # => true
"Hello World".is_a? Fixnum # => false
"Hello World".is_a? Object # => true
What methods are there?
The
methods
method returns an array of method names for an object, while a call on methods
from the class will produce an array of class methods."Hello".methods
String.methods
There are also methods that list more particular methods, such as
public_instance_methods
or private_methods
.You can also check if an object has an associated method with the
respond_to?
or method_defined?
methods. Unlike methods
, these two methods will not find private methods. The respond_to?
method really does what it say - it tells you if the object will respond to the method call, rather than if the method exists. Often an object can respond to method calls where there is no method present using the method_missing
functionality (discussed here). Rails uses this a lot. For a model, Post, calling Post.methods
will locate no find
methods, but the respond_to?
method confirms they are there. method_defined?
will tell you if the method actually exists."Hello".respond_to? 'length' # => true
String.respond_to? 'constants' # => true
Post.respond_to? 'find_by_name' # => true
Post.method_defined? 'find_by_name' # => false
See also:
http://www.ruby-doc.org/docs/ProgrammingRuby/html/ospace.html
Dynamically adding a method
You can add a method to a class at runtime, using the
define_method
method. Note that this method is private (so the first attempt below results in an error), and so must be invoked with the send
method.a = "what".class.define_method('hello') {p 'Hello World'}
# => NoMethodError: private method `define_method' called for String:Class
a = "what".class.send(:define_method, 'hello') {p 'Hello World'}
# => #<Proc:0x08cb9294@(irb):17>
irb(main):018:0> "say hello".hello
# => Hello World
You can even replace existing methods:
"what".length
=> 4
a = "random".class.send(:define_method, 'length') { 10 }
=> #<Proc:0x08caaf28@(irb):21>
"what".length
=> 10
Alternatively (and more simply), you can define methods for existing classes just like you would for your own class. The first example could be done like this:
class String
def hello
p 'Hello World'
end
end
I can see security issues here if someone can change how your classes' behave at runtime, and how do you comprehensively unit test if you cannot be sure how the String class behaves? All part of the fun of a dynamic language...
ObjectSpace
ObjectSpace
is the Ruby reflection mechanism. It is a module that tracks all the current objects. You can list them with this:ObjectSpace.each_object{ i puts i}
I had over 8000 objects in one IRB session. You can specify the class of an object to list, for example, this will list all objects of the Class class (only 466 of them):
ObjectSpace.each_object(Class) { i puts i}
Creating new objects dynamically
You can use the
ObjectSpace
to create a new object from a string containing the class name (see here), but I prefer using the eval
method. eval
simply interprets a given string as Ruby (like the synonymous method in JavaScript). The eval
method is none too fast, but I do not know how it compares to using ObjectSpace
.def create_object class_name
eval("#{class_name}.new")
end
Struggling with Ruby: Contents Page
No comments:
Post a Comment