We will be creating several files in this exercise, so to keep things organized, begin by creating a subdirectory named ruby within your lab10 directory and cd to that subdirectory.
Let's begin looking at inheritence in Ruby by building a superclass called Bird from which our Duck, Goose, and Owl classes will derive their functionality.
To start, use your favorite text editor to open a file named Bird.rb and copy the following class skeleton into it:
# Bird.rb | Defines a Bird superclass
# to be extended by specific bird sub-classes.
#
# Begun by: Dr. Adams, for CS 214 at Calvin College.
# Completed by:
# Date:
####################################################
class Bird
attr_reader :name
def initialize(name)
@name = name
end
end
As you can see, the constructor (the initialize method) and the accessor for the name instance variable have already been set up for you. You'll need to add the call and print methods to finish the defenition (but not the class_name method as we'll soon see).
Since every bird needs to say something, we need to provide our Bird superclass with a definition of a general call method. It should return the string 'Squaaaaaaawk!', which is the sound every unknown bird makes.
In addition, we need to be able to print a message containing everything we need to know about our bird. It should output a string containing the bird's name, the specific class name (we'll get to this shortly), the string " says ", and the return value of the call method. As in previous exercises, you can use puts to output this string to the screen, and the + symbol to concatenate two strings.
Now you may be asking where we get the specific class name from in Ruby? In other languages such a feat would be difficult and so we might instead simply hard code in the name as a string. In Ruby however, we can access the class name with the expression:
self.class.to_sThis attribute comes in handy for more advanced inheritance features of Ruby, but for now it'll serve us well to tell us what kind of bird we're dealing with.
Putting all of this together gives us these function definitions:
class Bird
attr_reader :name
def initialize(name)
@name = name
end
def call
'Squaaaaaaawk!'
end
def className
self.class.to_s
end
def print
puts name + className + " says " + call
end
end
Now that we've declared our Bird superclass, we need to declare our Duck, Goose, and Owl subclasses. Open a new file Owl.rb and add the following class skeleton to it:
# Owl.rb | Defines the Owl class which inherits attributes and methods # from the Bird superclass. # # Begun by: Dr. Adams, for CS 214 at Calvin College. # Completed by: # Date: #################################################### require './Bird.rb' class Owl < Bird end
As you might have guessed the < (less than) symbol is what triggers inheritance in Ruby. We use it here to make Owl a subclass of Bird. (This kind of inheritence is single inheritance. Ruby also supports multiple inheritance through constructs called modules and mixins.)
Once you've copied the class into Owl.rb, you'll need to write a class-specific call method. It shouldn't be too difficult — use the method from Bird as a model and change the string from 'Squaaaaaaawk!' to 'Whoo-hoo'. Once you've done that, you're done! Since we didn't need to hard-code in the class name, there's no need to override the className method that Owl inherits from Bird. And since we didn't add any attributes to our class, there's no need to define a new constructor.
Now just repeat this process to define Duck and Goose classes. Once you've done that, all that's left is test our code.
# birds.rb | Tests out the menagerie of bird classes. # # Begun by: Dr. Adams, for CS 214 at Calvin College. # Completed by: # Date: ###################################################### require './Bird.rb' require './Duck.rb' require './Goose.rb' require './Owl.rb' puts "\nWelcome to the Bird Park!\n\n" bird0 = Bird.new "Hawkeye" bird0.print bird1 = Duck.new "Donald" bird1.print bird2 = Goose.new "Mother" bird2.print bird3 = Owl.new "Woodsey" bird3.print puts "\n\n"Save, and test your creation by entering the following command on the command-line:
ruby birds.rbIf all is well, each of your flock should do their own things. If not, find and fix the errors before proceeding.
As we have defined it, each bird's name and class-name are jammed together. Find and improve this by making a space appear between each bird's name and class-name. Note that thanks to inheritance and polymorphism, you only have to make this change in one place, and all of our birds inherit that change.
Finally, tweak it so that when a bird's call is displayed, it is surrounded by double-quote (") characters. (You will probably need to use the escape sequence \".) As before, you should only have to make this change in one place.
Turn In. When all is correct, create a script file script.ruby in which you (i) run your program to show that it works correctly, and (ii) use cat to display the contents of each of your .rb files.
That concludes the Ruby part of this lab.
If this was your last exercise, return to the lab 10 page and follow the "Turn In" instructions there.
Calvin > CS > 214 > Labs > 10 > Ruby