Ruby教程

Ruby基础

开始

查看当前ruby的版本号,最新的版本是1.9:

>%ruby -v
ruby 1.9.0 (2006-06-08) [i486-linux]
交互式ruby:

ruby方式:

>%ruby
print "hello world"

^D  #Ctrl+D结束当前语句,显示结果并退回shell
hello world

irb方式:

>irb(main):001:0> print "hello world"
hello world=> nil

irb(main):002:0> exit
#注意最后一条语句不能出现;否则irb会让你继续输入
irb(main):002:0> print "hello world";   #此处有;号

irb(main):003:0* print "demy"            #irb会让你继续输入,认为是多条语句
hello worldok=> nil
irb(main):004:0> exit   #exit退出


###另一个例子
irb(main):001:0> def sum(n1,n2)
irb(main):002:1>   n1+n2
irb(main):003:1> end
=> nil

irb(main):004:0> sum(3,4)
=> 7
irb(main):005:0> sum("cat","dog")
=> "catdog"

###导入外部文件
% irb
irb(main):001:0> load "code/rdoc/fib_example.rb"
=> true
irb(main):002:0> Fibonacci.upto(20)
=> [1, 1, 2, 3, 5, 8, 13]

也可以通过ruby -e来制定语句,和perl,sed这些一样,后面跟ruby语句

>%ruby -e "print 'hello world'"
hello world
ruby程序:
>%ruby test.rb
Hello World
%cat test.rb

#!/usr/bin/ruby -w
puts "Hello World"
#或者用./test.rb
ruby文档:RDoc和ri

如果ruby的源文件是用RDoc生成的,那么文档则可以被转换成html和ri格式。

>#寻找一个类的文档,使用ri+类名的格式

%ri GC
Class:
GC
The GC module provides an interface to Rubys mark and sweep
garbage collection mechanism. Some of the underlying methods are
also available via the ObjectSpace module.
Class
methods:
disable, enable, start
Instance methods:
garbage_collect
#寻找方法的文档
% ri start
More than one method matched your request. You can refine
your search by asking for information on one of:
Date#new_start, Date#start, GC::start, Logger::Application#start,
Thread::start

#指定类名和方法
% ri GC.start
GC::
start
GC.start => nil
gc.garbage_collect => nil
ObjectSpace.garbage_collect => nil
Initiates
garbage collection, unless manually disabled.

设置ri的显示模式:

>% export RI="format ansi width 70"

Ruby.new

ruby是一种面向对象的语言

在ruby中,对象是由构造器构造,标准的构造方法是new

>song1 = Song.new("Ruby Tuesday")
song2 = Song.new("Enveloped in Python")

# and so on

ruby是完全OO的,可以和其他语言进行比较

>number = Math.abs(number) // Java code
number = number.abs
Ruby基础

以一个简单的ruby程序开始:

>def say_goodnight(name)
    result = "Good night, " + name
    return result
end
# Time for bed...

puts say_goodnight("JohnBoy")
puts say_goodnight("MaryEllen")

字符串内的表达式内插:

>def say_goodnight(name)
    result = "Good night, #{name}" # #{}是固定模式,也可以跟方法#{name.capitalize}

    return result
    end
puts say_goodnight('Pa')
结果:
Good night, Pa

当#{}里面的值只是全局,实例或者类的变量的话,不需要{}

>$greeting = "Hello" # $greeting 代表全局变量
@name = "Prudence" # @name 是实例变量

puts "#$greeting, #@name"
结果:
Hello, Prudence

数组和Hash:

>a = [ 1, 'cat', 3.14 ] # 包含3个元素的数组

# access the first element
a[0]->1
# 设置第3个元素的值
a[2] = nil
a->[1, "cat", nil]

变量类型:

局部全局实例(类属性)类(static)常量
name$debug@name@@totalPI
fish_and_chips$CUSTOMER@point_1@@symtabFeetPerMile
x_axis$_ @X@@NString
thx1138$plan9@_@@x_posMyClass
_26$Global@plan9@@SINGLEJazzSong

有的时候创建数组可能会麻烦因为包含了引号和逗号,在ruby中可以用%w来构建数组:

>a = [ 'ant', 'bee', 'cat', 'dog', 'elk' ]
a[0] ! "ant"

a[3] ! "dog"
#下面的一样
a = %w{ ant bee cat dog elk }
a[0] -> "ant"
a[3] -> "dog"

Hash的构造和Perl一样:

>inst_section = {

'cello' => 'string',
'clarinet' => 'woodwind',
'drum' => 'percussion',

'oboe' => 'woodwind',
'trumpet' => 'brass',
'violin' => 'string'

}

Hash中元素的访问:

>inst_section['oboe'] ->"woodwind"
inst_section['cello'] -> "string"

inst_section['bassoon'] -> nil

下面这个例子示范了,一个hash返回nil当key不存在时,但是hash也可以指定当key不存在时的值,通过new来构造hash

>histogram = Hash.new(0)
histogram['key1'] -> 0
histogram['key1'] = histogram['key1'] + 1
histogram['key1'] -> 1

控制结构:

>#if语句
if count > 10
puts "Try again"
elsif tries == 3
puts "You lose"

else
puts "Enter a number"
end
#while语句
while weight < 100 and num_pallets <= 30
pallet = next_pallet()
weight += pallet.weight
num_pallets += 1

end
while line = gets
puts line.downcase
end


square = 2
while square < 1000
square = square*square
end

#简洁模式,和perl有些类似
puts "Danger, Will Robinson" if radiation > 3000
square = 2
square = square*square while square < 1000

正则表达式:

>if line =~ /Perl|Python/
puts "Scripting language mentioned: #{line}"
end

line.sub(/Perl/, 'Ruby') # 将第一个'Perl'替换成'Ruby'
line.gsub(/Python/, 'Ruby') # 替换所有'Python'成'Rub

语句块和迭代器

>{ puts "Hello" } # 这是语句块
do ###
club.enroll(person) #这也是一个语句块

person.socialize #
end

当你创建了一个语句块后,你可以通过一个方法来绑定它。通过将语句块的开始放在包含方法后面

>def greet
 puts "greet"

end
greet { puts "Hi" }  #语句块和greet方法绑定
->greet #默认并不会附加语句块的结果
verbose_greet("Dave", "loyal customer") { puts "Hi" } #如果方法有参数

如果需要用到绑定的语句块,需要通过yield的关键字

>def call_block
    puts "Start of method"
    yield
    yield

    puts "End of method"
end
call_block { puts "In the block" }
结果:
Start of method
In the block

In the block
End of method

你也可以给yield设定参数

>def call_block
    yield("hello", 99)

end
call_block {|str, num| ... }

通过iterator遍历数组

>animals = %w( ant bee cat dog elk ) # create an array
animals.each {|animal| puts animal } # iterate over the contents
[ 'cat', 'dog', 'horse' ].each {|name| print name, " " }
5.times { print "*" }
3.upto(6) {|i| print i }
('a'..'e').each {|char| print char }

读和写:

>printf("Number: %5.2f,/nString: %s/n", 1.23, "hello")
Number: 1.23,
String: hello
#读入用户输入
while gets

if /Ruby/
    print
end
end

在以前ruby很多都借用了perl,读入用户输入可以这样

>while gets

if /Ruby/
    print
end
end

但是不推荐,推荐用ruby的方式

>ARGF.each {|line| print line if line =~ /Ruby/ }

也可以更简洁
print ARGF.grep(/Ruby/)

类对象和变量

initialize是类中一个特殊的方法,构造方法

>class Song

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

测试

>song = Song.new("Bicylops", "Fleck", 260)
song.inspect -> #<Song:0x1c7ca8 @name="Bicylops", @duration=260,
@artist="Fleck"

song = Song.new("Bicylops", "Fleck", 260)
song.to_s -> "#<Song:0x1c7ec4>" #Object ID


#重写 to_s方法
class Song
def to_s
    "Song: #@name----#@artist (#@duration)"

end
end
song = Song.new("Bicylops", "Fleck", 260)
song.to_s -> "Song: BicylopsFleck
(260)"

继承和消息

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

end
end
<Song代表 KaraokeSong是Song的子类

对象和属性

访问对象的属性

>class Song

def name
    @name
end
def artist
    @artist
end

def duration
    @duration
end
end
song = Song.new("Bicylops", "Fleck", 260)
song.artist -> "Fleck"

song.name -> "Bicylops"
song.duration -> 260

这种方式太繁琐,可以用attr_reader

>class Song
    attr_reader :name, :artist, :duration

end
#后面的结果和前面的一样

虚拟属性

>class Song
def duration_in_minutes

    @duration/60.0 # force floating point
end
def duration_in_minutes=(new_duration)
    @duration = (new_duration*60).to_i
end
end

song = Song.new("Bicylops", "Fleck", 260)
song.duration_in_minutes -> 4.33333333333333
song.duration_in_minutes -> 4.2
song.duration -> 252

类变量

>class Song

    @@plays = 0
    def initialize(name, artist, duration)
        @name = name
        @artist = artist
        @duration = duration
        @plays = 0
    end


    def play
        @plays += 1 # same as @plays = @plays + 1
        @@plays += 1
        "This song: #@plays plays. Total #@@plays plays."

    end
end

类方法

>class Example
    def instance_method # 实例方法

    end
    def Example.class_method # 类方法
    end
end

类方法其实可以有多种方法

>class Demo
def Demo.meth1
# ...
end
def self.meth2

# ...
end
class <<self
def meth3
# ...
end
end

end

单例设计模式和其他

>class MyLogger
private_class_method :new

@@logger = nil
def MyLogger.create

@@logger = new unless @@logger
@@logger

end
end

访问控制

>class MyClass
def method1 # default is 'public'

#...
end
protected # subsequent methods will be 'protected'
def method2 # will be 'protected'
#...
end

private # subsequent methods will be 'private'
def method3 # will be 'private'
#...
end
public # subsequent methods will be 'public'
def method4 # and this will be 'public'

#...
end
end

#或者可以用列表的方法设定控制层级
class MyClass
def method1

end
# ... and so on
public :method1, :method4
protected :method2
private :method3
end

保护访问

>class Account
attr_reader :balance # accessor method 'balance'
protected :balance # and make it protected

def greater_balance_than(other)
return @balance > other.balance
end
end
变量

注意ruby里面变量并不是对象,只是对象的引用而已,下面的例子可以说明

>person1 = "Tim"
person2 = person1
person1[0] = 'J'
person1 -> "Jim"
person2 -> "Jim"

person1到person2的赋值并没有改变对象的值,只是拷贝person1这个引用到person2而已

改变这种方式可以用dup

>person1 = "Tim"
person2 = person1.dup
person1[0] = "J"
person1 -> "Jim"

person2 -> "Tim"

也可以保护某个特定的Object不被改变,这时使用freeze

>person1 = "Tim"
person2 = person1
person1.freeze # prevent modifications to the object

person2[0] = "J"

结果:
prog.rb:4:in `[]=': can't modify frozen string (TypeError)  #报错误
from prog.rb:4

容器,语句块,迭代器

容器
数组
>a = [ 3.14159, "pie", 99 ]
a.class -> Array
a.length -> 3
a[0] -> 3.14159

b = Array.new
b.class -> Array

b.length -> 0

Array通过[]被索引

>a = [ 1, 3, 5, 7, 9 ]
a[1]->9
a[2]->7
a[99]->nil

也可以用[start,end]来索引,slice

>a = [ 1, 3, 5, 7, 9 ]
a[1, 3] -> [3, 5, 7]
a[3, 1] -> [7]
a[3,2] -> [5, 7]

可以更简洁

>a = [ 1, 3, 5, 7, 9 ]
a[1..3] -> [3, 5, 7]
a[1...3] -> [3, 5]
a[3..3] -> [7]
a[3..1] -> [5, 7, 9]

Hash

>h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' }
h.length -> 3
h['dog'] -> "canine

实现一个songlist

>class SongList

def initialize
@songs = Array.new

end

def append(song)
@songs.push(song)
self
end

def delete_first

@songs.shift
end

def delete_last
@songs.pop
end

def [](index)

@songs[index]
end

end

如果要实现songlist的with_title方法

>def with_title(title)
for i in 0...@songs.length

return @songs[i] if title == @songs[i].name
end
return nil
end

#可以更简洁,可以用find实现
class SongList
def with_title(title)
@songs.find {|song| title == song.name }
end
end

实现迭代器

yield的用法

>def three_times
yield
yield
yield

end
three_times { puts "Hello"}

def fib_up_to(max)
i1, i2 = 1, 1 # parallel assignment (i1 = 1 and i2 = 1)
while i1 <= max
yield i1
i1, i2 = i2, i1+i2

end
end
fib_up_to(1000) {|f| print f, " " }

遍历

>a = [1, 2]
b = 'cat'
a.each {|b| c = b * a[1] }

find实现方式

>class Array
def find
for i in 0...size
value = self[i]

return value if yield(value)
end
return nil
end
end

[1, 3, 5, 7, 9].find {|v| v*v > 30 } ! 7

另一个通常的iterator是collect,语句的结果用来构造来一个新的array

>["H", "A", "L"].collect {|x| x.succ } => ["I", "B", "M"]

再看一个更加有用的iterator,inject,inject让你从列表中计算某个值

>[1,3,5,7].inject(0) {|sum, element| sum+element} -> 16
[1,3,5,7].inject(1) {|product, element| product*element} -> 105

inject的工作的方式是这样,inject中的值赋值给sum,element被赋值给collection中的第一个值,第2次,block返回的值再赋值给sum,element取collection中第2个值,如此得到最后的值

注意:如果Inject没有参数的话,默认取collection的第一个数据做为参数,从collection第2个数据开始计算

>[1,3,5,7].inject {|sum, element| sum+element} -> 16
[1,3,5,7].inject {|product, element| product*element} -> 105
>class File
def File.open_and_process(*args)
f = File.open(*args)

yield f
f.close()
end
end

class File
def File.my_open(*args)
result = file = File.new(*args)

# If there's a block, pass in the file and close
# the file when it returns
if block_given?
result = yield file
file.close
end
return result
end

end

lambda表达式

>def n_times(thing)
return lambda {|n| thing * n }
end
>3.times { print "X " }
1.upto(5) {|i| print i, " " }
99.downto(95) {|i| print i, " " }
50.step(80, 5) {|i| print i, " " }

表达式内插可以支持复杂的语句

>puts "now is #{ def the(a)
'the ' + a
end
the('time')
} for all good coders..."

String的构造

>%q/general singlequoted
string/ -> general singlequoted
string
%Q!general doublequoted
string! -> general doublequoted
string
%Q{Seconds/day: #{24*60*60}} -> Seconds/day: 86400

通过heredocument构造String

>string = <<END_OF_STRING
The body of the string
is the input lines up to
one ending with the same
text that followed the '<<'
END_OF_STRING
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值