Ruby,2008-02-17

############################### Class ##############################

class Song

def initialize(name, artist, duration)

@name = name

@artist = artist

@duration = duration

end

end

#initialize is a special method in Ruby programs.When you call Song.new to create

#a new Song object, Ruby allocates some memory to hold an uninitialized object and

#then calls that object’s initialize method, passing in any parameters that were passed to new.

#In Ruby, an instance variable is simply a name preceded by an “at” sign (@).

song = Song.new("Bicylops", "Fleck", 260)

puts song.inspect

song1 = Song.new "Bicylops", "Fleck", 260

puts song1.to_s

#In Ruby, classes are never closed: you can always add methods to an existing class.

#We said that Ruby supports to_s for all objects

class Song

def to_s

"Song: #@name--#@artist (#@duration)"

end

end

song = Song.new("Bicylops", "Fleck", 260)

puts song.to_s

################################## Inheritance and Messages #######################

class KaraokeSong < Song

def initialize(name, artist, duration, lyrics)

super(name, artist, duration)

@lyrics = lyrics

end

end

song = KaraokeSong.new("my Way", "Sinatra", 225, "And now, the...")

puts song.to_s

#when Ruby comes across the method invocation song.to_s, it doesn’t actually know

#where to find the method to_s. Instead, it defers the decision until the program is run.

#At that time, it looks at the class of song. If that class implements a method with the

#same name as the message, that method is run. Otherwise, Ruby looks for a method in

#the parent class, and then in the grandparent, and so on up the ancestor chain. If it runs

#out of ancestors without finding the appropriate method, it takes a special action that

#normally results in an error being raised.

class KaraokeSong < Song

def to_s

super + " [#@lyrics]"

end

end

song = KaraokeSong.new("my Way", "Sinatra", 225, "And now, the...")

puts song.to_s

################################# Objects and Attributes ####################

#Ruby offers an interesting and powerful compromise, giving you

#the simplicity of single inheritance and the power of multiple inheritance.

#A Ruby class has only one direct parent, so Ruby is a singleinheritance

#language. However, Ruby classes can include the functionality

#of any number of mixins (a mixin is like a partial class definition).

#This provides a controlled multiple-inheritance-like capability

#with none of the drawbacks.

class Song

def name

@name

end

def artist

@artist

end

def duration

@duration

end

end

song = Song.new("Bicylops", "Fleck", 260)

puts song.artist

puts song.name

puts song.duration

#Because this is such a common idiom, Ruby provides a convenient shortcut:

#attr_reader creates these accessor methods for you.

#In this example, we named the accessor methods name, artist, and

#duration. The corresponding instance variables, @name, @artist, and @duration,

#will be created automatically.

class Song

attr_reader :name, :artist, :duration

end

song = Song.new("Bicylops", "Fleck", 260)

puts song.artist

puts song.name

puts song.duration

################################### Writable Attributes ############################

class Song

def duration=(new_duration)

@duration = new_duration

end

end

song = Song.new("Bicylops", "Fleck", 260)

puts song.duration

song.duration = 257

puts song.duration

#Ruby provides a shortcut for creating these simple attribute-setting methods.

class Song

attr_writer :duration

end

song = Song.new("Bicylops", "Fleck", 260)

song.duration = 257

############################ Virtual Attributes ###########################

class Song

def duration_in_minutes

@duration / 60.0

end

def duration_in_minutes=(new_duration)

@duration = (new_duration * 60)

end

end

song = Song.new("Bicylops", "Fleck", 260)

puts song.duration_in_minutes

song.duration_in_minutes = 4.2

puts song.duration

############################# Class Variables #############################

#A class variable is shared among all objects of a class.

#class variables must be initialized before they are used.

class Song

@@plays = 0

def initialize(name, artist, duration)

@name = name

@artist = artist

@duration = duration

@plays = 0

end

def play

@plays += 1

@@plays += 1

end

end

s1 = Song.new("Song1", "Artist1", 234)

s2 = Song.new("Song2", "Artist2", 345)

s1.play

s2.play

s1.play

s2.play

#Class variables are private to a class and its instances. If you want to make them accessible

#to the outside world, you’ll need to write an accessor method. This method could

#be either an instance method

######################################### Class Methods #####################

class Example

#instance method

def instance_method

end

#class method

def Example.class_method

end

end

class SongList

MAX_TIME = 5 * 60

def SongList.is_too_long(song)

return song.duration > MAX_TIME

end

end

song1 = Song.new("Bicylops", "Fleck", 260)

SongList.is_too_long(song1)

song2 = Song.new("The Calling", "Santana", 468)

SongList.is_too_long(song2)