From: Robert Klemme Date: 2009-08-12T05:10:13+09:00 Subject: Re: Which initialize method? (or, who is self?) On 11.08.2009 21:23, Daniel Waite wrote: > Hi. Consider the ruby-hmac gem: > http://pastie.org/580360 > > Line 81 makes the following call: > hmac = self.new(key) > > But, insofar as I understand Ruby's wonderful world context switching, > self, in the instance in which it is called, is both unnecessary On first inspection, yes. But not if you look closer: > (because the method in which it is being called is already part of the > class) and incorrect (because the only initialize method available > requires more than one argument). The method invoked is #new and not #initialize! This means that argument lists of new and initialize need not be identical. You can create a class whose Method.new has different arguments than #initialize: class Foo def self.new(x) o = allocate o.send(:initialize, x, 1, 2) o end def initialize(a, b, c) # ... end end In this case it works differently though: > The file works (in some instances...), so I'll assume my understanding > of Ruby is still poor. Which sucks because I thought I knew it fairly > well. > > I've tried printing out self in each new context, and I get the expected > result (HMAC::Base). Except, that is, inside a Rails application running > on Ruby 1.9.1, in which case I get HMAC::SHA1 within the Base.digest > method. Awesome. > > Any ideas? The fact that the class is called "Base" indicates that it is intended for inheritance. I don't have a Ruby interpreter at hand right now to cook up a tested example, but considering inheritance and the fact that class methods are inherited by subclasses the whole thing actually makes sense: class SHA1 < Base def initialize(key) super(SHA1, 1024, 4096, key) end end Now line 99 makes sense in combination with 81 / 91: Base.new is private which will make self.new() trigger an exception and thus prevent invocation of Base.digest() and Base.hexdigest(). But, you can invoke SHA1.digest() and it will work. Arguments algorithm, block_size and output_length to Base.initialize are actually class dependent, i.e. every subclass likely defines their own values. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/