[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Basic Inheritance questions {noob alert:- pickaxe ed. 2, page 27}

John Maclean

1/20/2006 7:21:00 PM

Chaps,

Say you have a class Song. You'd make a file for that class with the
following;

#!/usr/bin/env ruby
class Song
def initialize(name, artist, duration)
# define instance variables
@name = name
@artist = artist
@duration = duration
end

def to_s
# method for displaying these instancess
"Song: #@name--#@artist (#@duration)"
end
end

# test the class by creating a new object
#song = Song.new("Bicylops", "Fleck", 260)
#song.inspect

Now it's time to make a "child" class....

jayeola@tp20$ cat class_KaraokeSong.rb
#!/usr/bin/env ruby
class KaraokeSong < Song
def initialize(name, artist, duration, lyrics)
super(name, artist, duration)
@lyrics = lyrics
end

# def to_s
# # method for displaying these instancess
# "Song: #@name--#@artist (#@duration)"
# end
end

When I created the parent it was simple to `irb` and then `require
class_Song.rb`.

How would one use this child class? Not quite clear from the Pickaxe
book. Do I create a new file for KaraokeSong as I have done or have
both the "super" and "child" in the same file?

--
John Maclean
MSc (DIC)
07739 171 531



13 Answers

Wilson Bilkovich

1/20/2006 7:28:00 PM

0

You can do it one of three ways:
In IRB, require the Song file, and then the KaraokeSong file, in that order

John Maclean

1/20/2006 9:38:00 PM

0

Thanks for that speedy reply. I've decided to require the within the
child. One thing to note is that when I do require the child irb shows
the following..

cat fx/ruby/chap3/class_KaraokeSong.rb

#!/usr/bin/env ruby
require 'class_Song.rb'

# test if this class has been loaded correctly
Object.const_defined?(:Song)

class KaraokeSong < Song
def to_s
super + " [#@lyrics]"
end
end

irb(main):011:0> require 'class_KaraokeSong.rb'
=> false



On Sat, 21 Jan 2006 04:28:25 +0900 Wilson Bilkovich
<wilsonb@gmail.com> wrote:

> You can do it one of three ways:
> In IRB, require the Song file, and then the KaraokeSong file, in that
> order. Edit the KaraokeSong file to require the Song before defining
> the child class. Put both of the class definitions in a single file,
> with the parent first, and then the child.
>
> In order for KaraokeSong < Song to work, this method needs to return
> true: Object.const_defined?(:Song)
> That will be the case with each of the three possibilities above.
>
> Good luck, and have fun,
> --Wilson.
>
> On 1/20/06, John Maclean <info@jayeola.org> wrote:
> > Chaps,
> >
> > Say you have a class Song. You'd make a file for that class with the
> > following;
> >
> > #!/usr/bin/env ruby
> > class Song
> > def initialize(name, artist, duration)
> > # define instance variables
> > @name = name
> > @artist = artist
> > @duration = duration
> > end
> >
> > def to_s
> > # method for displaying these instancess
> > "Song: #@name--#@artist (#@duration)"
> > end
> > end
> >
> > # test the class by creating a new object
> > #song = Song.new("Bicylops", "Fleck", 260)
> > #song.inspect
> >
> > Now it's time to make a "child" class....
> >
> > jayeola@tp20$ cat class_KaraokeSong.rb
> > #!/usr/bin/env ruby
> > class KaraokeSong < Song
> > def initialize(name, artist, duration, lyrics)
> > super(name, artist, duration)
> > @lyrics = lyrics
> > end
> >
> > # def to_s
> > # # method for displaying these instancess
> > # "Song: #@name--#@artist (#@duration)"
> > # end
> > end
> >
> > When I created the parent it was simple to `irb` and then `require
> > class_Song.rb`.
> >
> > How would one use this child class? Not quite clear from the Pickaxe
> > book. Do I create a new file for KaraokeSong as I have done or have
> > both the "super" and "child" in the same file?
> >
> > --
> > John Maclean
> > MSc (DIC)
> > 07739 171 531
> >
> >
> >
>
>
>


--
John Maclean
MSc (DIC)
07739 171 531



Eero Saynatkari

1/20/2006 10:03:00 PM

0

John Maclean wrote:
> Thanks for that speedy reply. I've decided to require the within the
> child. One thing to note is that when I do require the child irb shows
> the following..
>
> cat fx/ruby/chap3/class_KaraokeSong.rb
>
> #!/usr/bin/env ruby
> require 'class_Song.rb'
>
> # test if this class has been loaded correctly
> Object.const_defined?(:Song)
>
> class KaraokeSong < Song
> def to_s
> super + " [#@lyrics]"
> end
> end
>
> irb(main):011:0> require 'class_KaraokeSong.rb'
> => false

Getting a 'false' in irb means the file is already
loaded (a LoadError would be raised if the file could
not be found); if you want, you can use

load 'song.rb'

This will reload the file each time (seldomly necessary).

As a compatibility-note, you could make your filenames
all lowercase_and_underscored. This will thwart any
case sensitivity issues.

E


--
Posted via http://www.ruby-....


John Maclean

1/20/2006 10:12:00 PM

0

Thanks for another fast response. Inheritance - I'm going to get this
-tonight-!

recap;
# the parent class
cat fx/ruby/chap3/class_Song.rb
#!/usr/bin/env ruby
class Song
def initialize(name, artist, duration)
# define instance variables
@name = name
@artist = artist
@duration = duration
end

def to_s
# method for displaying these instancess
"Song: #@name--#@artist (#@duration)"
end
end

# the child class

jayeola@tp20$ cat fx/ruby/chap3/class_KaraokeSong.rb
#!/usr/bin/env ruby
require 'class_Song.rb'

# test if this class has been loaded correctly
Object.const_defined?(:Song)

class KaraokeSong < Song
def initialize(name, artist, duration, lyrics)
super(name, artist, duration)
@lyrics = lyrics
end

def to_s
super + " [#@lyrics]"
end
end

#song = KaraokeSong.new("My Way", "Sinatra", 225, "And now, the...")
#song = KaraokeSong.new("Sinatra", 225, "And now, the...")
#song.to_s
#song.inspect


How do we get KaraokeSong to acquire it's parent's attributes -without-
hadrcoding "def initialize(name, artist, duration, lyrics)", unless one
has to? From the book I get the impression that you can get away with
specifying the child's stuff and that it will take properties from it's
parent with the keyword super....


--
John Maclean
MSc (DIC)
07739 171 531



Eero Saynatkari

1/20/2006 10:37:00 PM

0

John Maclean wrote:
> Thanks for another fast response. Inheritance - I'm going to get this
> -tonight-!
>
> recap;
> # the parent class
> cat fx/ruby/chap3/class_Song.rb
> #!/usr/bin/env ruby
> class Song
> def initialize(name, artist, duration)
> # define instance variables
> @name = name
> @artist = artist
> @duration = duration
> end
>
> def to_s
> # method for displaying these instancess
> "Song: #@name--#@artist (#@duration)"
> end
> end
>
> # the child class
>
> jayeola@tp20$ cat fx/ruby/chap3/class_KaraokeSong.rb
> #!/usr/bin/env ruby
> require 'class_Song.rb'
>
> # test if this class has been loaded correctly
> Object.const_defined?(:Song)
>
> class KaraokeSong < Song
> def initialize(name, artist, duration, lyrics)
> super(name, artist, duration)
> @lyrics = lyrics
> end
>
> def to_s
> super + " [#@lyrics]"
> end
> end
>
> #song = KaraokeSong.new("My Way", "Sinatra", 225, "And now, the...")
> #song = KaraokeSong.new("Sinatra", 225, "And now, the...")
> #song.to_s
> #song.inspect
>
>
> How do we get KaraokeSong to acquire it's parent's attributes -without-
> hadrcoding "def initialize(name, artist, duration, lyrics)", unless one
> has to? From the book I get the impression that you can get away with
> specifying the child's stuff and that it will take properties from it's
> parent with the keyword super....

If the child needs additional parameters (or otherwise overrides
the corresponding method in the parent class), you must* define
the method in the child (super will run the parent's method like
in your #initialize above). When the parent's behaviour is adequate,
you do not need to define a method, it is automatically inherited.

An alternative would be to just have an accessor for @lyrics; that
way you would not need to define #initialize, but you would need to
call #lyrics= to set the lyrics initially., which on the surface
would seem the more cumbersome way.


E

* Not strictly true; you could circumvent this with some careful
metaprogramming but it really is not worth it in this situation.

--
Posted via http://www.ruby-....


John Maclean

1/21/2006 12:11:00 AM

0

I'm sorry I still don't get it. (To be honest I think that I can narrow
down this problem to the book not having all of the code in a single
place)...

I can understand that for example (p27) is telling us that there's a
"right way" and "wrong way" to specify methods for child instances.. so
what's wrong with this?

#!/usr/bin/env ruby
require 'class_Song.rb'

# test if this class has been loaded correctly
Object.const_defined?(:Song)

class KaraokeSong < Song
# grab all the properties from the parent but add another instance
variable
def initialize(lyrics)
@lyrics = lyrics
end

def to_s
super + " [#@lyrics]"
end
end

song = KaraokeSong.new("And now, the...")
#song = KaraokeSong.new("My Way", "Sinatra", 225, "And now, the...")
song.inspect
song.to_s
puts song

The above has not specified a name, artist and duration - but that's
coming from the parent class, is it not?


jayeola@tp20$ ruby -w class_KaraokeSong.rb
/class_Song.rb:12: warning: instance variable @name not initialized
/class_Song.rb:12: warning: instance variable @artist not initialized
/class_Song.rb:12: warning: instance variable @duration not initialized
/class_Song.rb:12: warning: instance variable @name not initialized
/class_Song.rb:12: warning: instance variable @artist not initialized
/class_Song.rb:12: warning: instance variable @duration not initialized
Song: -- () [And now, the...]



On Sat, 21 Jan 2006 07:37:03 +0900
Eero Saynatkari <ruby-forum-reg@mailinator.com> wrote:

> John Maclean wrote:
> > Thanks for another fast response. Inheritance - I'm going to get
> > this -tonight-!
> >
> > recap;
> > # the parent class
> > cat fx/ruby/chap3/class_Song.rb
> > #!/usr/bin/env ruby
> > class Song
> > def initialize(name, artist, duration)
> > # define instance variables
> > @name = name
> > @artist = artist
> > @duration = duration
> > end
> >
> > def to_s
> > # method for displaying these instancess
> > "Song: #@name--#@artist (#@duration)"
> > end
> > end
> >
> > # the child class
> >
> > jayeola@tp20$ cat fx/ruby/chap3/class_KaraokeSong.rb
> > #!/usr/bin/env ruby
> > require 'class_Song.rb'
> >
> > # test if this class has been loaded correctly
> > Object.const_defined?(:Song)
> >
> > class KaraokeSong < Song
> > def initialize(name, artist, duration, lyrics)
> > super(name, artist, duration)
> > @lyrics = lyrics
> > end
> >
> > def to_s
> > super + " [#@lyrics]"
> > end
> > end
> >
> > #song = KaraokeSong.new("My Way", "Sinatra", 225, "And now, the...")
> > #song = KaraokeSong.new("Sinatra", 225, "And now, the...")
> > #song.to_s
> > #song.inspect
> >
> >
> > How do we get KaraokeSong to acquire it's parent's attributes
> > -without- hadrcoding "def initialize(name, artist, duration,
> > lyrics)", unless one has to? From the book I get the impression that
> > you can get away with specifying the child's stuff and that it will
> > take properties from it's parent with the keyword super....
>
> If the child needs additional parameters (or otherwise overrides
> the corresponding method in the parent class), you must* define
> the method in the child (super will run the parent's method like
> in your #initialize above). When the parent's behaviour is adequate,
> you do not need to define a method, it is automatically inherited.
>
> An alternative would be to just have an accessor for @lyrics; that
> way you would not need to define #initialize, but you would need to
> call #lyrics= to set the lyrics initially., which on the surface
> would seem the more cumbersome way.
>
>
> E
>
> * Not strictly true; you could circumvent this with some careful
> metaprogramming but it really is not worth it in this situation.
>


--
John Maclean
MSc (DIC)
07739 171 531



Tim Hunter

1/21/2006 12:25:00 AM

0

John Maclean wrote:

> class KaraokeSong < Song
> # grab all the properties from the parent but add another instance
> variable
> def initialize(lyrics)
> @lyrics = lyrics
> end
>
> def to_s
> super + " [#@lyrics]"
> end
> end

When you call KaraokeSong.new, the KaraokeSong initialize method is
called, so it needs to accept all the arguments and then pass the args
that Song's initialize method needs to it via 'super':

def initialize(name, artist, duration, lyrics)
super(name, artist, duration)
@lyrics = lyrics
end

Mike Stok

1/21/2006 12:27:00 AM

0


On 20-Jan-06, at 7:11 PM, John Maclean wrote:

> I'm sorry I still don't get it. (To be honest I think that I can
> narrow
> down this problem to the book not having all of the code in a single
> place)...
>
> I can understand that for example (p27) is telling us that there's a
> "right way" and "wrong way" to specify methods for child
> instances.. so
> what's wrong with this?
>
> #!/usr/bin/env ruby
> require 'class_Song.rb'
>
> # test if this class has been loaded correctly
> Object.const_defined?(:Song)
>
> class KaraokeSong < Song
> # grab all the properties from the parent but add another instance
> variable
> def initialize(lyrics)

... shouldn't you have a call like

super('','','')

here to initialise the parent class variables?

> @lyrics = lyrics
> end
>
> def to_s
> super + " [#@lyrics]"
> end
> end
>
> song = KaraokeSong.new("And now, the...")
> #song = KaraokeSong.new("My Way", "Sinatra", 225, "And now, the...")
> song.inspect
> song.to_s
> puts song
>
> The above has not specified a name, artist and duration - but that's
> coming from the parent class, is it not?
>
>
> jayeola@tp20$ ruby -w class_KaraokeSong.rb
> ./class_Song.rb:12: warning: instance variable @name not initialized
> ./class_Song.rb:12: warning: instance variable @artist not initialized
> ./class_Song.rb:12: warning: instance variable @duration not
> initialized
> ./class_Song.rb:12: warning: instance variable @name not initialized
> ./class_Song.rb:12: warning: instance variable @artist not initialized
> ./class_Song.rb:12: warning: instance variable @duration not
> initialized
> Song: -- () [And now, the...]
>
>
>
> On Sat, 21 Jan 2006 07:37:03 +0900
> Eero Saynatkari <ruby-forum-reg@mailinator.com> wrote:
>
>> John Maclean wrote:
>>> Thanks for another fast response. Inheritance - I'm going to get
>>> this -tonight-!
>>>
>>> recap;
>>> # the parent class
>>> cat fx/ruby/chap3/class_Song.rb
>>> #!/usr/bin/env ruby
>>> class Song
>>> def initialize(name, artist, duration)
>>> # define instance variables
>>> @name = name
>>> @artist = artist
>>> @duration = duration
>>> end
>>>
>>> def to_s
>>> # method for displaying these instancess
>>> "Song: #@name--#@artist (#@duration)"
>>> end
>>> end
>>>
>>> # the child class
>>>
>>> jayeola@tp20$ cat fx/ruby/chap3/class_KaraokeSong.rb
>>> #!/usr/bin/env ruby
>>> require 'class_Song.rb'
>>>
>>> # test if this class has been loaded correctly
>>> Object.const_defined?(:Song)
>>>
>>> class KaraokeSong < Song
>>> def initialize(name, artist, duration, lyrics)
>>> super(name, artist, duration)
>>> @lyrics = lyrics
>>> end
>>>
>>> def to_s
>>> super + " [#@lyrics]"
>>> end
>>> end
>>>
>>> #song = KaraokeSong.new("My Way", "Sinatra", 225, "And now, the...")
>>> #song = KaraokeSong.new("Sinatra", 225, "And now, the...")
>>> #song.to_s
>>> #song.inspect
>>>
>>>
>>> How do we get KaraokeSong to acquire it's parent's attributes
>>> -without- hadrcoding "def initialize(name, artist, duration,
>>> lyrics)", unless one has to? From the book I get the impression that
>>> you can get away with specifying the child's stuff and that it will
>>> take properties from it's parent with the keyword super....
>>
>> If the child needs additional parameters (or otherwise overrides
>> the corresponding method in the parent class), you must* define
>> the method in the child (super will run the parent's method like
>> in your #initialize above). When the parent's behaviour is adequate,
>> you do not need to define a method, it is automatically inherited.
>>
>> An alternative would be to just have an accessor for @lyrics; that
>> way you would not need to define #initialize, but you would need to
>> call #lyrics= to set the lyrics initially., which on the surface
>> would seem the more cumbersome way.
>>
>>
>> E
>>
>> * Not strictly true; you could circumvent this with some careful
>> metaprogramming but it really is not worth it in this situation.
>>
>
>
> --
> John Maclean
> MSc (DIC)
> 07739 171 531
>
>
>

--

Mike Stok <mike@stok.co.uk>
http://www.stok.co...

The "`Stok' disclaimers" apply.






Mike Stok

1/21/2006 12:28:00 AM

0


On 20-Jan-06, at 7:11 PM, John Maclean wrote:

> I'm sorry I still don't get it. (To be honest I think that I can
> narrow
> down this problem to the book not having all of the code in a single
> place)...
>
> I can understand that for example (p27) is telling us that there's a
> "right way" and "wrong way" to specify methods for child
> instances.. so
> what's wrong with this?
>
> #!/usr/bin/env ruby
> require 'class_Song.rb'
>
> # test if this class has been loaded correctly
> Object.const_defined?(:Song)
>
> class KaraokeSong < Song
> # grab all the properties from the parent but add another instance
> variable
> def initialize(lyrics)

... shouldn't you have a call like

super('','','')

here to initialise the parent class variables?

> @lyrics = lyrics
> end
>
> def to_s
> super + " [#@lyrics]"
> end
> end
>
> song = KaraokeSong.new("And now, the...")
> #song = KaraokeSong.new("My Way", "Sinatra", 225, "And now, the...")
> song.inspect
> song.to_s
> puts song
>
> The above has not specified a name, artist and duration - but that's
> coming from the parent class, is it not?
>
>
> jayeola@tp20$ ruby -w class_KaraokeSong.rb
> ./class_Song.rb:12: warning: instance variable @name not initialized
> ./class_Song.rb:12: warning: instance variable @artist not initialized
> ./class_Song.rb:12: warning: instance variable @duration not
> initialized
> ./class_Song.rb:12: warning: instance variable @name not initialized
> ./class_Song.rb:12: warning: instance variable @artist not initialized
> ./class_Song.rb:12: warning: instance variable @duration not
> initialized
> Song: -- () [And now, the...]
>
>
>
> On Sat, 21 Jan 2006 07:37:03 +0900
> Eero Saynatkari <ruby-forum-reg@mailinator.com> wrote:
>
>> John Maclean wrote:
>>> Thanks for another fast response. Inheritance - I'm going to get
>>> this -tonight-!
>>>
>>> recap;
>>> # the parent class
>>> cat fx/ruby/chap3/class_Song.rb
>>> #!/usr/bin/env ruby
>>> class Song
>>> def initialize(name, artist, duration)
>>> # define instance variables
>>> @name = name
>>> @artist = artist
>>> @duration = duration
>>> end
>>>
>>> def to_s
>>> # method for displaying these instancess
>>> "Song: #@name--#@artist (#@duration)"
>>> end
>>> end
>>>
>>> # the child class
>>>
>>> jayeola@tp20$ cat fx/ruby/chap3/class_KaraokeSong.rb
>>> #!/usr/bin/env ruby
>>> require 'class_Song.rb'
>>>
>>> # test if this class has been loaded correctly
>>> Object.const_defined?(:Song)
>>>
>>> class KaraokeSong < Song
>>> def initialize(name, artist, duration, lyrics)
>>> super(name, artist, duration)
>>> @lyrics = lyrics
>>> end
>>>
>>> def to_s
>>> super + " [#@lyrics]"
>>> end
>>> end
>>>
>>> #song = KaraokeSong.new("My Way", "Sinatra", 225, "And now, the...")
>>> #song = KaraokeSong.new("Sinatra", 225, "And now, the...")
>>> #song.to_s
>>> #song.inspect
>>>
>>>
>>> How do we get KaraokeSong to acquire it's parent's attributes
>>> -without- hadrcoding "def initialize(name, artist, duration,
>>> lyrics)", unless one has to? From the book I get the impression that
>>> you can get away with specifying the child's stuff and that it will
>>> take properties from it's parent with the keyword super....
>>
>> If the child needs additional parameters (or otherwise overrides
>> the corresponding method in the parent class), you must* define
>> the method in the child (super will run the parent's method like
>> in your #initialize above). When the parent's behaviour is adequate,
>> you do not need to define a method, it is automatically inherited.
>>
>> An alternative would be to just have an accessor for @lyrics; that
>> way you would not need to define #initialize, but you would need to
>> call #lyrics= to set the lyrics initially., which on the surface
>> would seem the more cumbersome way.
>>
>>
>> E
>>
>> * Not strictly true; you could circumvent this with some careful
>> metaprogramming but it really is not worth it in this situation.
>>
>
>
> --
> John Maclean
> MSc (DIC)
> 07739 171 531
>
>
>

--

Mike Stok <mike@stok.co.uk>
http://www.stok.co...

The "`Stok' disclaimers" apply.






Eero Saynatkari

1/21/2006 1:00:00 AM

0

John Maclean wrote:
> I'm sorry I still don't get it. (To be honest I think that I can narrow
> down this problem to the book not having all of the code in a single
> place)...
>
> I can understand that for example (p27) is telling us that there's a
> "right way" and "wrong way" to specify methods for child instances.. so
> what's wrong with this?
>
> #!/usr/bin/env ruby
> require 'class_Song.rb'
>
> # test if this class has been loaded correctly
> Object.const_defined?(:Song)
>
> class KaraokeSong < Song
> # grab all the properties from the parent but add another instance
> variable
> def initialize(lyrics)
> @lyrics = lyrics
> end
>
> def to_s
> super + " [#@lyrics]"
> end
> end
>
> song = KaraokeSong.new("And now, the...")
> #song = KaraokeSong.new("My Way", "Sinatra", 225, "And now, the...")

There is no #initialize method that takes four parameters
at this point (see below).

> song.inspect
> song.to_s
> puts song
>
> The above has not specified a name, artist and duration - but that's
> coming from the parent class, is it not?

All you are getting from the parent class are the actual
variables and an #initialize method that takes three parameters.
In your child class, you define a new #initialize that only takes
one parameter (overriding the one from the parent class) so that
all KaraokeSong.new can see is the one with just one parameter.

Even if the child class had a method looking like this:

def initialize(lyrics)
super
@lyrics = lyrics
end

The problem would still be that the method itself does not
take more than one parameter and you would see an error if
you tried to pass it four. So the correct way indeed is to
have your child class with an #initialize that takes all
four parameters and then call #super with the three parameters
that must go to the parent- (or super-) class.

> < Warning messages elided />


E

--
Posted via http://www.ruby-....