Learn to Program(3)

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

你可能感兴趣的:(r)