On Sun, Feb 23, 2003 at 04:24:37AM +0900, Mark Wilson wrote: > > On Saturday, February 22, 2003, at 09:31 AM, Gavin Sinclair wrote: > > >[snip] > >It's perfectly obvious at a glance to me. True, I've faced difficulty > >with such concepts in the past (at one point, I didn't understand the > >class << self business), but working through those difficulties is > >necessary to become proficient in Ruby. > > > >Not that I'm suggesting that difficult code be written for the sake of > >it. Only that there's no point shying away from complex-seeming > >constructs which, thankfully, are part of the consistency of the > >language. > >[snip] > > Gavin, > > Your message raises the obvious question for me -- given that I don't > understand the 'class << self' business -- what is the meaning and > usage of 'class << self'? Please help me truly understand. Thanks. (skip as much as required :) class << someobj end allows you to add singleton methods to one object (that is, add methods to its singleton class). >> a = "aaa" => "aaa" >> class << a >> def foo >> puts "ho" * 3 >> end >> end => nil >> a.foo hohoho => nil Classes are objects too >> class A; end => nil >> A.id => 538275918 and as such you can add singleton methods to them: >> class << A >> def bar >> puts "bar" * 4 >> end >> end => nil >> A.bar barbarbarbar => nil Now, inside class A; ....; end, self refers to the class object (that of class Class :) >> A.id => 538275918 >> class A; self.id; end => 538275918 >> class A; self.class; end => Class Now we use both 'class << someobj' and the fact that, inside the 'class SomeClass; .... ; end' construct, self refers to the class. We thus add singleton methods, that is, class methods >> class A >> class << self >> def baz >> puts "baz " * 4 >> end >> end >> end => nil >> A.baz baz baz baz baz => nil So that idiom corresponds to doing >> def A.baz2 >> puts "baz " * 4 >> end => nil >> A.baz2 baz baz baz baz => nil One cool thing about singleton method definitions is that they can be nested inside other method defs: >> def foo(a) >> def a.babar >> puts "I am #{self.id}" >> end >> end => nil >> b = "fdgdfgf" => "fdgdfgf" >> foo(b) => nil >> b.babar I am 538152868 => nil That is equivalent to >> def foo(a) >> class << a >> def babar >> puts "My id is #{self.id}" >> end >> end >> end => nil >> b = "abcd" => "abcd" >> foo(b) => nil >> b.babar My id is 538276118 => nil One reason to prefer 'class << obj' over 'def obj.' is that it is possible to capture the singleton class that way: >> class << b; self; end => String # reported as 'String' but it is actually the singleton class of b! Imagine for instance that you don't want the singleton class (and therefore the singleton methods) of an object to be modified; you'd do class << someobj; self.freeze; end -- _ _ | |__ __ _| |_ ___ _ __ ___ __ _ _ __ | '_ \ / _` | __/ __| '_ ` _ \ / _` | '_ \ | |_) | (_| | |_\__ \ | | | | | (_| | | | | |_.__/ \__,_|\__|___/_| |_| |_|\__,_|_| |_| Running Debian GNU/Linux Sid (unstable) batsman dot geo at yahoo dot com - long f_ffree; /* free file nodes in fs */ + long f_ffree; /* freie Dateiknoten im Dateisystem */ -- Seen in a translation