Learn to Program(3)
9. Classes
Objects in Ruby are always capitalized. String, Integer, Float, Array...
a = Array.new([1,3,3])
b = String.new('carl')
c = Time.new
puts a.to_s
puts b.to_s
puts c.to_s
results are :
[1, 3, 3]
carl
2011-08-10 16:39:01 +0800
9.1 The Time Class
time = Time.new
time2 = time + 60 # one minute later
puts time
puts time2
puts Time.mktime(1982,4,5)
puts Time.mktime(1982,4,5,23,50,59)
9.2 The Hash Class
Hashes are a lot like arrays. It is just like the Map class in Java.
colorArray = []
colorHash = {}
colorArray[0] = 'red'
colorArray[1] = 'green'
colorHash['strings'] = 'red'
colorHash['numbers'] = 'green'
colorHash['keywords']= 'blue'
colorArray.each do |color|
puts color
end
colorHash.each do |codeType,color|
puts codeType + ": " + color
end
9.3 Extending Classes
It seems a miracle to extends the class here.
class Integer
def to_eng
if self == 5
english = 'five'
end
if self == 6
english = 'six'
end
english
end
end
puts 5.to_eng
puts 6.to_eng
9.4 Creating Classes
class Die
def roll
1 + rand(6)
end
end
dice = [Die.new,Die.new,Die.new]
dice.each do |die|
puts die.roll
end
9.5 Instance Variables
An instance of a class is just an object of that class. So instance variables are just an object's variables.To tell instance variables from
local variables, they have @ in front of their names:
class Die
def roll
@number = 1 + rand(6)
end
def show
@number
end
end
die = Die.new
die.roll
puts die.show
die.roll
puts die.show
We can initial the class first.
class Die
def initialize
roll
end
...snip...
end
When an object is created, its initialize method (if it has one defined) is always called.
10. Blocks and Procs
It is the ability to take a block of code (code in between do and end), wrap it up in an object (called a proc), store it in a variable or pass it to a method, and run the code in the block whenever you feel like.
toast = Proc.new do
puts 'Cheers!'
end
toast.call
toast.call
Proc which is supposed to be short for 'procedure'. It rhymes with 'block'.
It is even more like a method, because blocks can take parameters.
doyoulike = Proc.new do |goodthing|
puts 'I really like ' + goodthing + '!'
end
doyoulike.call 'chocolate'
In particular, you can't pass methods into other methods, but you can pass procs into methods.
Methods can't return other methods, but they can return procs.
The root reason is procs are objects, methods are not.
10.1 Methods Which Take Procs
def doSelfImportantly someProc
puts 'Everybody just HOLD ON! I have something to do...'
someProc.call
puts 'Ok everyone, I\'m done. Go on with what you were doing.'
end
sayHello = Proc.new do
puts 'hello'
end
sayGoodbye = Proc.new do
puts 'goodbye'
end
doSelfImportantly sayHello
doSelfImportantly sayGoodbye
Complex example.
def doUntilFalse firstInput, someProc
input = firstInput
output = firstInput
while output
input = output
output = someProc.call input
end
input
end
buildArrayOfSquares = Proc.new do |array|
lastNumber = array.last
if lastNumber <= 0
false
else
array.pop # Take off the last number...
array.push lastNumber*lastNumber # ...and replace it with its square...
array.push lastNumber-1 # ...followed by the next smaller number.
end
end
alwaysFalse = Proc.new do |justIgnoreMe|
false
end
puts doUntilFalse([5], buildArrayOfSquares).inspect
puts doUntilFalse('I\'m writing this at 3:00 am; someone knock me out!', alwaysFalse)
The inspect method is a lot like to_s.
10.2 Methods Which Return Procs
def compose proc1, proc2
Proc.new do |x|
proc2.call(proc1.call(x))
end
end
squareIt = Proc.new do |x|
x * x
end
doubleIt = Proc.new do |x|
x + x
end
doubleThenSquare = compose doubleIt, squareIt
squareThenDouble = compose squareIt, doubleIt
puts doubleThenSquare.call(5)
puts squareThenDouble.call(5)
Make 2 procs to 1 proc and return proc in the method.
10.3 Passing Blocks (Not Procs) Into Methods
class Array
def eachEven(&wasABlock_nowAProc)
isEven = true # We start with "true" because arrays start with 0, which is even.
self.each do |object|
if isEven
wasABlock_nowAProc.call object
end
isEven = (not isEven) # Toggle from even to odd, or odd to even.
end
end
end
['apple', 'bad apple', 'cherry', 'durian'].eachEven do |fruit|
puts 'Yum! I just love '+fruit+' pies, don\'t you?'
end
# Remember, we are getting the even-numbered elements
# of the array, all of which happen to be odd numbers,
# just because I like to cause problems like that.
[1, 2, 3, 4, 5].eachEven do |oddBall|
puts oddBall.to_s+' is NOT an even number!'
end
&name, bring block to the methods. Another example.
def profile descriptionOfBlock, &block
startTime = Time.now
block.call
duration = Time.now - startTime
puts descriptionOfBlock+': '+duration.to_s+' seconds'
end
profile '25000 doublings' do
number = 1
25000.times do
number = number + number
end
puts number.to_s.length.to_s+' digits' # That is, the number of digits in this HUGE number.
end
profile 'count to a million' do
number = 0
1000000.times do
number = number + 1
end
end
results are as follow:
7526 digits
25000 doublings: 0.1092 seconds
count to a million: 0.124801 seconds
references:
http://pine.fm/LearnToProgram/?Chapter=09
9. Classes
Objects in Ruby are always capitalized. String, Integer, Float, Array...
a = Array.new([1,3,3])
b = String.new('carl')
c = Time.new
puts a.to_s
puts b.to_s
puts c.to_s
results are :
[1, 3, 3]
carl
2011-08-10 16:39:01 +0800
9.1 The Time Class
time = Time.new
time2 = time + 60 # one minute later
puts time
puts time2
puts Time.mktime(1982,4,5)
puts Time.mktime(1982,4,5,23,50,59)
9.2 The Hash Class
Hashes are a lot like arrays. It is just like the Map class in Java.
colorArray = []
colorHash = {}
colorArray[0] = 'red'
colorArray[1] = 'green'
colorHash['strings'] = 'red'
colorHash['numbers'] = 'green'
colorHash['keywords']= 'blue'
colorArray.each do |color|
puts color
end
colorHash.each do |codeType,color|
puts codeType + ": " + color
end
9.3 Extending Classes
It seems a miracle to extends the class here.
class Integer
def to_eng
if self == 5
english = 'five'
end
if self == 6
english = 'six'
end
english
end
end
puts 5.to_eng
puts 6.to_eng
9.4 Creating Classes
class Die
def roll
1 + rand(6)
end
end
dice = [Die.new,Die.new,Die.new]
dice.each do |die|
puts die.roll
end
9.5 Instance Variables
An instance of a class is just an object of that class. So instance variables are just an object's variables.To tell instance variables from
local variables, they have @ in front of their names:
class Die
def roll
@number = 1 + rand(6)
end
def show
@number
end
end
die = Die.new
die.roll
puts die.show
die.roll
puts die.show
We can initial the class first.
class Die
def initialize
roll
end
...snip...
end
When an object is created, its initialize method (if it has one defined) is always called.
10. Blocks and Procs
It is the ability to take a block of code (code in between do and end), wrap it up in an object (called a proc), store it in a variable or pass it to a method, and run the code in the block whenever you feel like.
toast = Proc.new do
puts 'Cheers!'
end
toast.call
toast.call
Proc which is supposed to be short for 'procedure'. It rhymes with 'block'.
It is even more like a method, because blocks can take parameters.
doyoulike = Proc.new do |goodthing|
puts 'I really like ' + goodthing + '!'
end
doyoulike.call 'chocolate'
In particular, you can't pass methods into other methods, but you can pass procs into methods.
Methods can't return other methods, but they can return procs.
The root reason is procs are objects, methods are not.
10.1 Methods Which Take Procs
def doSelfImportantly someProc
puts 'Everybody just HOLD ON! I have something to do...'
someProc.call
puts 'Ok everyone, I\'m done. Go on with what you were doing.'
end
sayHello = Proc.new do
puts 'hello'
end
sayGoodbye = Proc.new do
puts 'goodbye'
end
doSelfImportantly sayHello
doSelfImportantly sayGoodbye
Complex example.
def doUntilFalse firstInput, someProc
input = firstInput
output = firstInput
while output
input = output
output = someProc.call input
end
input
end
buildArrayOfSquares = Proc.new do |array|
lastNumber = array.last
if lastNumber <= 0
false
else
array.pop # Take off the last number...
array.push lastNumber*lastNumber # ...and replace it with its square...
array.push lastNumber-1 # ...followed by the next smaller number.
end
end
alwaysFalse = Proc.new do |justIgnoreMe|
false
end
puts doUntilFalse([5], buildArrayOfSquares).inspect
puts doUntilFalse('I\'m writing this at 3:00 am; someone knock me out!', alwaysFalse)
The inspect method is a lot like to_s.
10.2 Methods Which Return Procs
def compose proc1, proc2
Proc.new do |x|
proc2.call(proc1.call(x))
end
end
squareIt = Proc.new do |x|
x * x
end
doubleIt = Proc.new do |x|
x + x
end
doubleThenSquare = compose doubleIt, squareIt
squareThenDouble = compose squareIt, doubleIt
puts doubleThenSquare.call(5)
puts squareThenDouble.call(5)
Make 2 procs to 1 proc and return proc in the method.
10.3 Passing Blocks (Not Procs) Into Methods
class Array
def eachEven(&wasABlock_nowAProc)
isEven = true # We start with "true" because arrays start with 0, which is even.
self.each do |object|
if isEven
wasABlock_nowAProc.call object
end
isEven = (not isEven) # Toggle from even to odd, or odd to even.
end
end
end
['apple', 'bad apple', 'cherry', 'durian'].eachEven do |fruit|
puts 'Yum! I just love '+fruit+' pies, don\'t you?'
end
# Remember, we are getting the even-numbered elements
# of the array, all of which happen to be odd numbers,
# just because I like to cause problems like that.
[1, 2, 3, 4, 5].eachEven do |oddBall|
puts oddBall.to_s+' is NOT an even number!'
end
&name, bring block to the methods. Another example.
def profile descriptionOfBlock, &block
startTime = Time.now
block.call
duration = Time.now - startTime
puts descriptionOfBlock+': '+duration.to_s+' seconds'
end
profile '25000 doublings' do
number = 1
25000.times do
number = number + number
end
puts number.to_s.length.to_s+' digits' # That is, the number of digits in this HUGE number.
end
profile 'count to a million' do
number = 0
1000000.times do
number = number + 1
end
end
results are as follow:
7526 digits
25000 doublings: 0.1092 seconds
count to a million: 0.124801 seconds
references:
http://pine.fm/LearnToProgram/?Chapter=09