From: Robert Klemme Date: 2006-07-10T02:30:14+09:00 Subject: Re: Definition of methods: self Damaris Fuentes wrote: > Ok, thanks for the explanations! > But...now that you mention the concatenator... I will comment another > problem in this entry. (I write all the code, ven though perhaps you > don't need it) > > The problem here is that the re- definition ot a class (LotteryDraw) > doesn't seem to see the attributes of the first definition. > > I have the class ot the lottery ticket: > *********************** > class LotteryTicket > NUMERIC_RANGE = 1..25 > attr_reader :picks > > def initialize( *picks ) > [...] > @picks = picks > end > > def score( final ) > count = 0 > final.picks.each do |note| > count +=1 if picks.include? note > end > count > end > > end > > ***************************** > Now I have the lottery draw, where I store the buyers of the tickets: > ********************** > class LotteryDraw > @@tickets = {} > def LotteryDraw.buy( customer, *tickets ) > unless @@tickets.has_key?( customer ) > @@tickets[customer] = [] > end > @@tickets[customer] += tickets > end > end > ******* > And NOW, I REDEFINE THE CLASS with the concatenator, adding a new class > method: > ******************** > class << LotteryDraw > def play > final = LotteryTicket.new_random > winners = {} > @@tickets.each do |buyer, ticket_list| > ticket_list.each do |ticket| > score = ticket.score( final ) > next if score.zero? > winners[buyer] ||= [] > winners[buyer] << [ ticket, score ] > end > end > @@tickets.clear > winners > end > end > ******** > > And now I execute the following: > ************************ > LotteryDraw.buy('JuanMi', > LotteryTicket.new( 12, 6, 19 ), > LotteryTicket.new( 5, 1, 3 ), > LotteryTicket.new( 24, 6, 8 )) > > LotteryDraw.buy('Da', > LotteryTicket.new( 18, 4, 7 ), > LotteryTicket.new( 21, 25, 3 ), > LotteryTicket.new( 12, 17, 19 )) > > LotteryDraw.play.each do |winner, tickets| > puts winner + "won on " + tickets.length + " ticket(s)!" > tickets.each do |ticket, score| > puts "\t" + ticket.picks.join( ', ' ) + ": " + score > end > end > ************************************ > > And an exception arises: > in `play': uninitialized class variable @@tickets in Object. > This exception appears in the trace: > - LotteryDraw.play.each do |winner, tickets|, > - @@tickets.each do |buyer, ticket_list| (in LotteryDraw.play) > > What is the problem? Thanks (and sorry if this is very long :() > Without looking too closely at your code I'm guessing that it's because your class methods are in the singleton class of LotteryDraw - and so lookups for class variables are done in *that* hierarchy and not in the one of LotteryDraw. I generally recommend to not use class variables because they introduce all sorts of weirdnesses. I'd rather use a normal instance variable of the class instance. That's accessible for sure in the singleton method. Kind regards robert