Reflection refers to facilities in a language that allow the programmer to examine aspects of the program from within the program itself. This is discussed in more detail in Chapter 26 of the Programming Ruby book.
ObjectSpace.each_object(PosRational) {|x| p x}(each_object takes a class as an argument, and a block, and invokes the block for each instance in memory of the class or a subclass of it. p prints the object followed by a newline -- convenient for experimenting in irb.)
Note that using respond_to? is more duckly than using kind_of?.
Classes are also objects! Try these:
3.class Fixnum.superclass Object.superclass Fixnum.ancestors (note that this includes mixins)
Examples to ponder:
3.class 3.class.class 3.class.class.class 3.class.class.class.class
What's going on here? Since classes are objects, they must be instances of some class. In Ruby, this is the class Class. And Class is an instance of itself!
We can also ask a class more specific questions about its methods. First let's define an example class:
class Octopus @@octo_var = 2 # class variable TENTACLES = 8 # constant def initialize(n) @name = n end def speak puts "I'm an octopus named #{@name}" puts private_method end def print_vars puts @@octo_var puts TENTACLES end # this is the standard way to write a class method in Ruby def self.classgreeting puts "hi from class Octopus" end def self.otherclassgreeting puts "another hello" end private def private_method "calling a private method in Octopus" end end # to try: # o = Octopus.new("oscar") # o.speak # o.print_vars # Octopus.classgreeting
Now try these:
Octopus.private_instance_methods(false) Octopus.public_instance_methods(false) Octopus.public_instance_methods(true) # include ancestors Octopus.constants Octopus.class_variables Octopus.singleton_methods
Also see the Ruby docs for Class.
We can make new classes (i.e. instance of Class) by sending Class the new message (with an optional argument that is the superclass). This creates an anonymous class -- we haven't necessarily bound it to a name.
o = Octopus.new("oscar") o.send(:speak) a = "s" + "peak" b = a.to_sym o.send(b)
How to grab a method:
s = o.method(:speak) s.call # m1 is an unbound method m1 = Octopus.instance_method(:speak) m2 = m1.bind(o) m2.call
Ruby has an eval method:
eval("3+4") x =42 eval("x")You can also pass an environment to eval:
def test v = 42 binding end b = test # b is now a binding that includes the variable v eval("v+5", b) eval("v=100", b) b.local_variables
An object can have its own methods or instance variables. This is implemented by creating a singleton class for it (also known as an eigenclass).
s = "I am a string ...." class <<s attr_accessor :squid def greet "hi there" end end
Now s has a greet method and a squid attribute! (But just s, not all strings.) Try this:
s.singleton_methods
Singleton classes are also used to handle class variables and class methods. For example, the class Octopus above has a class method named classgreeting. This is in the singleton class for Octopus. See Chapter 24 of the Ruby book for more details.