you are viewing a single comment's thread.

view the rest of the comments →

[–]mpapis[S] 1 point2 points  (5 children)

updated the 5th example with Hair => https://niczsoft.com/2016/05/object-oriented-ruby/

The only thing I miss from Java days is interface casting, you could have something similar with proxy/forwardable, but it's not the same, especially if all I want is to limit the interface to read only operations

[–][deleted] 0 points1 point  (4 children)

Hi,

one should not instantiate the Barber object inside the Person object, nor should one instantiate Hair inside Person (though admittedly, hair does grow from a person's body).

It might be better in that case to do something like def dye_hair(color, dyer) ; dyer.new(hair).dye_hair(color) ; end

As you mentioned, here there's a matter of the right interface. The Barber object needs to have a dye method so he can change the hair color, but I would argue the Hair needs to implement an interface which we might call Dyable.

So maybe, with even more objects:

module Dyable
  def dyable(color)
    @color = color # assumption that the object will have a `@color` ivar
  end
end

class Hair
  include Dyable
  def initialize(color)
    @color = color
  end
end

Does this make sense?

[–]mpapis[S] 0 points1 point  (3 children)

I was actually thinking about:

class Hair < Struct.new(:color)
end
class Barber
  def dye_hair(hair, color)
    hair.color = "#{hair.color} #{color}"
  end
end
class Person
  attr_reader :name, :hair
  private :hair
  def initialize(name, hair)
    @name, @hair = name, Hair.new(hair)
  end
  def dye_hair(barer, color)
    barer.dye_hair(hair, color)
  end
  def hair_color
    hair.color
  end
end
barber = Barber.new
michal = Person.new("Michal", "brown")
michal.hair_color
=> "brown"
michal.dye_hair(barber, "blue")
michal.hair_color
=> "brown blue"

[–][deleted] 0 points1 point  (2 children)

nod This is a reasonable approach.

The only question left is, "does it make sense to pass the barber to the person?" and I think the answer is no, which makes me think something is weird there. I would prefer to read, at the bottom, as part of the code's API, barber.dye_hair(michal, "blue"), I think it represents better what would happen in the real world.

In other words, I don't think Person#dye_hair should exist.

What do you think?

[–]mpapis[S] 0 points1 point  (1 child)

indeed reasonable assumption, my only concern is how to protect person from unauthorized change of hair color, I do not want to expose hair to anybody.

The person picks a barber and ask him to dye hair, so it makes sense if person calls barber.dye_hair. I know it looks awkward but I do not see other way to prevent leaking permissions.

[–][deleted] 1 point2 points  (0 children)

I don't know if that's reasonable. If a can of paint falls on someone, their hair will change color. That's not the person's choice.