Ruby class relationships: how to use methods and objects from another class?
Thanks for looking at my question! :)
I am new to Ruby programming and I am having a hard time figuring out how to implement classes in my code and inherit their methods and variables from each other.
I have a LightBulb class that looks like this:
class LightBulb
def initialize( watts, on )
@watts = watts
@on = on
end
# accessor methods
def watts
@watts
end
def on
@on
end
# other methods
def turnon
@on = true
end
def turnoff
@on = false
end
def to_s
"#{@watts}-#{@on}"
end
end
and the driver program that works with the class:
# a lit, 30-watt bulb
b = LightBulb.new( 30, false )
b.turnon( )
Bulb
# a 50-watt bulb
fiftyWatt = LightBulb.new( 50, false )
fiftyWatt.turnoff( )
... and I'm trying to create a Lamp class that has a LightBulb and uses it at different times. I know that in the inheritance tree diagram they should be next to each other (e.g. LightBulb - Lamp, instead of LightBulb <- Lamp), so I don't know if <inheritance should be used. Here is the basic structure I need for the Lamp class:
Lamp ( string make, string model, double cost, int watts )
-- accessors
string make( )
string model( )
-- methods
void turnon( ) # turn on the bulb
void turnoff( ) # turn off the bulb
--class members
string make
string model
double cost
LightBulb bulb
How can I use the turnon () and turnoff () methods from the LightBulb class, and the bulb object in the Lamp class?
Here's what I have for the lamp now, but I'm sure most of them are wrong:
class Lamp
attr_accessor :watts
def initialize(make, model, cost, watts)
@make = make
@model = model
@cost = cost
@watts = LightBulb.new(:watts)
end
def make
@make
end
def model
@model
end
def cost
@cost
end
end
source to share
You definitely don't need inheritance here. You compose these objects, the lamp has a LightBulb. You are close and all you really need to do is call the methods on LightBulb that you are missing:
class Lamp
def initialize(make, model, cost, watts)
@make = make
@model = model
@cost = cost
@bulb = LightBulb.new(watts, false)
end
# ...
def turnon
@bulb.turnon
end
def turnoff
@bulb.turnoff
end
end
So I changed @watts
to @bulb
and dropped the character :watts
since you really need to pass the value watts
that was passed in. If you're curious, here's some more information on symbols .
source to share
In object oriented terms, this can be done by delegating these methods:
class Lamp
def turnon
@lightbulb.turnof
end
def turnoff
@lightbulb.turnoff
end
end
These pass-through methods are quite common in Ruby code where you need to wrap one object inside another.
There is also a Forwardable module if you are feeling more adventurous.
From an object oriented design perspective, I'm more concerned about the chain of responsibility. For example, although the lamp has an on / off state, the lamp itself acts as a "controller". You are correct that this is not a case of inheritance, but instead of encapsulation.
source to share