views:

135

answers:

4

Hi,

I want to create an object, let's say a Pie.

class Pie 
  def initialize(name, flavor) 
    @name = name 
    @flavor = flavor 
  end 
end

But a Pie can be divided in 8 pieces, a half or just a whole Pie. For the sake of argument, I would like to know how I could give each Pie object a price per 1/8, 1/4 or per whole. I could do this by doing:

class Pie 
  def initialize(name, flavor, price_all, price_half, price_piece) 
    @name = name 
    @flavor = flavor 
    @price_all = price_all
    @price_half = price_half
    @price_piece = price_piece
  end 
end 

But now, if I would create fifteen Pie objects, and I would take out randomly some pieces somewhere by using a method such as

getPieceOfPie(pie_name)

How would I be able to generate the value of all the available pies that are whole and the remaining pieces? Eventually using a method such as:

   myCurrentInventoryHas(pie_name)
   # output: 2 whole strawberry pies and 7 pieces.

I know, I am a Ruby nuby. Thank you for your answers, comments and help!

+3  A: 

Could you create a PieSlice object, and each Pie would have an array of PieSlices?

JRL
Thats a great idea!!! Thanks a bunch!!
Shyam
A: 

A piece of pie is not a pie.

(talking in oo terms, an object should have a clear responsibility, making an object a pie AND a slice may not be a clear responsibility assignment).

baol
I do agree with you. And one of the reasons of asking this question is to figure out the solution using OO and elegancy.
Shyam
I think that if you have a Pie with an array of slices, there is no "violation" of the OO principles.
Shyam
It all depends on what you want to do with your pie and pieces. If you can assume that each piece is independent (you don't need to know if a pie is cut or not) you probably need only a PieInventory and a PiePiece. The inventory can grow and shrink as you call push_pieces(n) and pull_pieces(n).
baol
But what if I would want to know when a pie is cut? It is the whole idea of the question! I know, its an awkward one, but thats why its bugging me :)
Shyam
I would just suppose that you have n/8 pies and n%8 cut pieces. Why would you cut more than one pie at a time?
baol
+1  A: 

The Pie class could have a counter to indicate what fraction of it remains. The getPieceOfPie method would modify this counter. The myCurrentInventoryHas method could then look at each Pie and see how much of that Pie there is be examining the counter.

FrustratedWithFormsDesigner
+2  A: 

You'll definitely want separate Pie and PiePiece classes

class Pie
  attr_accessor :pieces
  def initialize
    self.pieces = []
  end

  def add_piece(flavor)
    raise "Pie cannot have more than 8 pieces!" if pieces.count == 8
    self.pieces << PiePiece.new(flavor)
  end

  # a ruby genius could probably write this better... chime in if you can help
  def inventory
    Hash[pieces.group_by(&:flavor).map{|f,p| [f, p.size]}]
  end

end

class PiePiece
  attr_accessor :flavor
  def initialize(flavor)
    self.flavor = flavor
  end
end

sample code

p = Pie.new
p.add_piece(:strawberry)
p.add_piece(:strawberry)
p.add_piece(:apple)
p.add_piece(:cherry)
p.add_piece(:cherry)
p.add_piece(:cherry)

p.inventory.each_pair do |flavor, count|
  puts "Pieces of #{flavor}: #{count}"
end

# output
# Pieces of strawberry: 2
# Pieces of apple: 1
# Pieces of cherry: 3
macek
Sweet, I like this answer. Indeed it's the inventory counting I'm struggling with. Thank you so much for helping out!
Shyam
@Shyam, I updated the post to show a *possible* way to do the inventory counting. Someone who has a better mastery of `Array` and `Hash` methods would probably be able to write it better though :)
macek
Excellent. No need for a genius, you already did a great job. Thanks!
Shyam
@Shyam, @mckeed helped out. I updated the `Pie#inventory` method to showcase his genius.
macek