Defining struct in a class

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' ) )

···

----- "William Song" <wei_song1990@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/\.

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.

···

On 2010-06-08 14:02:03 -0700, Wes Bailey said:

----- "William Song" <wei_song1990@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' ) )

--
Rein Henrichs

http://reinh.com

----- "Rein Henrichs" <reinh@reinh.com> wrote:

···

On 2010-06-08 14:02:03 -0700, Wes Bailey said:

> ----- "William Song" <wei_song1990@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.