From: Wes Bailey on 8 Jun 2010 17:02 ----- "William Song" <wei_song1990(a)hotmail.com> wrote: > How can I properly define a struct in a class? > > If I have > > class Cards > Card = Struct.new(:suit, :number) > @cardsOnHand=[] > > @cardsOnHand.push(Card.new("S","5")) > end > > This will give me an error message saying the push is not defined for > NilClass. How should I fix this? > -- > Posted via http://www.ruby-forum.com/. Your problem is not a struct but the fact that you are not properly instantiating an instance variable. I probably wouldn't use a struct like you have instead solve the problem understand that your cards class is a deck that structurally is just an array: class Deck < Array def add( card ) raise ArgumentError unless card.is_a?( Card ) # Other checks on how many cards per suite and not allowing duplicate cards self.push( card ) end end class Card attr_accessor :number, :suite def initialize( number, suite ) @number = number.to_s if /[2-9AKQJ]/.match( number.to_s ) @suite = suite.to_s if /[CHDS]/.match( suite.to_s ) raise Exception if @number.nil? || @suite.nil? end end deck = Deck.new deck.add( Card.new( 3, :H ) ) deck.add( Card.new( '4', 'S' ) )
From: Rein Henrichs on 9 Jun 2010 03:49 On 2010-06-08 14:02:03 -0700, Wes Bailey said: > ----- "William Song" <wei_song1990(a)hotmail.com> wrote: > >> How can I properly define a struct in a class? >> >> If I have >> >> class Cards >> Card = Struct.new(:suit, :number) >> @cardsOnHand=[] >> >> @cardsOnHand.push(Card.new("S","5")) >> end >> >> This will give me an error message saying the push is not defined for >> NilClass. How should I fix this? >> -- >> Posted via http://www.ruby-forum.com/. > > Your problem is not a struct but the fact that you are not properly > instantiating an instance variable. I probably wouldn't use a struct > like you have instead solve the problem understand that your cards > class is a deck that structurally is just an array: > > class Deck < Array > def add( card ) > raise ArgumentError unless card.is_a?( Card ) > # Other checks on how many cards per suite and not allowing duplicate cards > > self.push( card ) > end > end > > class Card > attr_accessor :number, :suite > > def initialize( number, suite ) > @number = number.to_s if /[2-9AKQJ]/.match( number.to_s ) > @suite = suite.to_s if /[CHDS]/.match( suite.to_s ) > > raise Exception if @number.nil? || @suite.nil? > end > end > > deck = Deck.new > > deck.add( Card.new( 3, :H ) ) > deck.add( Card.new( '4', 'S' ) ) > The fact that the Deck class violates the Liskov Substitution Principle should imply that a Deck is not necessarily an Array. For instance, the semantics of many Array and Enumerable methods would be undefined on a deck of cards. It would be better to create a Deck class that delegated semantically appropriate methods to an internal array object (using Forwardable, for instance) rather than expecting a Deck to conform to the entire Array interface. This is why it is, in general, somewhat dubious to subclass base classes for your own use, even when there seems to be a superficial similarity. Of course, none of this has anything to do with the original problem. -- Rein Henrichs http://puppetlabs.com http://reinh.com
From: Wes Bailey on 9 Jun 2010 12:35
[Note: parts of this message were removed to make it a legal post.] ----- "Rein Henrichs" <reinh(a)reinh.com> wrote: > On 2010-06-08 14:02:03 -0700, Wes Bailey said: > > > ----- "William Song" <wei_song1990(a)hotmail.com> wrote: > > > >> How can I properly define a struct in a class? > >> > >> If I have > >> > >> class Cards > >> Card = Struct.new(:suit, :number) > >> @cardsOnHand=[] > >> > >> @cardsOnHand.push(Card.new("S","5")) > >> end > >> > >> This will give me an error message saying the push is not defined for > >> NilClass. How should I fix this? > >> -- > >> Posted via http://www.ruby-forum.com/. > > > > Your problem is not a struct but the fact that you are not properly > > instantiating an instance variable. I probably wouldn't use a struct > > like you have instead solve the problem understand that your cards > > class is a deck that structurally is just an array: > > > > class Deck < Array > > def add( card ) > > raise ArgumentError unless card.is_a?( Card ) > > # Other checks on how many cards per suite and not allowing duplicate cards > > > > self.push( card ) > > end > > end > > > > class Card > > attr_accessor :number, :suite > > > > def initialize( number, suite ) > > @number = number.to_s if /[2-9AKQJ]/.match( number.to_s ) > > @suite = suite.to_s if /[CHDS]/.match( suite.to_s ) > > > > raise Exception if @number.nil? || @suite.nil? > > end > > end > > > > deck = Deck.new > > > > deck.add( Card.new( 3, :H ) ) > > deck.add( Card.new( '4', 'S' ) ) > > > > The fact that the Deck class violates the Liskov Substitution Principle > should imply that a Deck is not necessarily an Array. For instance, the > semantics of many Array and Enumerable methods would be undefined on a > deck of cards. It would be better to create a Deck class that delegated > semantically appropriate methods to an internal array object (using > Forwardable, for instance) rather than expecting a Deck to conform to > the entire Array interface. > > This is why it is, in general, somewhat dubious to subclass base > classes for your own use, even when there seems to be a superficial > similarity. > > Of course, none of this has anything to do with the original problem. > > -- > Rein Henrichs > http://puppetlabs.com > http://reinh.com Thanks for pointing that out Rein. You learn something new every day when active in this mailing list. Forwardable might be possible but I think you are right that Deck is really its own class that uses an array object as the internal data store. |