1 ruby 基础知识 ruby.new
ruby 字符串对象的处理:单引号--处理极少 ; 双引号--处理较多。
情况一: 反斜杠 (例如\n)会使用相应的二进制值替换它们。
情况二: #{表达式}替换, 为了方便,如果表达式是 全局实例变量 或者类变量 可以不适用花括号。例如:
@a = "zhang san" //实例变量
$b = "li si" //全局变量
@@c ="zhang wu" //类变量
puts "hello, #@a,\n #$b"
ruby命名惯例:
实例变量 @a 类变量@@a 全局变量$a--------变量的首字母须是小写字母或者下划线
类名className: A 、模块MoudleName:A 和常量 A --------首字母须大写
数组(array)与 散列表(hashes)
a= ["a","b","c"] a[0] => "a"
a= %w{a b c} a[0] => "a" 注: %w{} 使得空格的字符串形成数组
b={"a" => "bert","b" => "dota", "c" => "bobo"} 注:键与值,键(key)是唯一的。
b= Hash.new(0)
ruby的控制结构
大多数ruby语句会返回值,这就意味着可以把它们当做条件使用。例如,gets方法从标准输入流返回下一行,
或者到达文件结束时返回nil。
while line = gets
puts line.downcase
end
如果if或者while语句的程序体只是个表达式,ruby的语句修饰符是一种有用的快捷方式。
if radiation >3000
puts "danger,will robinson"
end
简写: puts "danger,will robinson" if radiation >3000
square = 2
while square <1000
square = square * square
end
简写:square =2
square = square*square while square < 1000
正则表达式对象
=~ 匹配操作符可以用正则表达式来匹配字符串。如果在字符串中发现了匹配的模式,=~ 返回模式的开始位置,否则返回nil。
if line=~ /perl|python/
puts "scripting language mentioned: #{line}"
end
ruby的匹配替换
line.sub(/perl/,'ruby') #用 'ruby'替换第一个'perl'
line.gsub(/python/,'ruby') #用'ruby'替换所有的'python'
Block和迭代器
block是ruby的独特特性,可以和方法调用相关联的代码块。
处在花括号中或者do...end之间便是block
{puts "hello world" } #this is a block 单行block
do
puts "hello sb" # and so is this 多行block
end
一旦创建了block,就可以与方法的调用相关联。把block的开始放在含有方法调用的源码行的结尾处,就可实现关联。
无参数的方法: greet {puts "Hi" }
有参数的方法: verbose_greet("dave","loa customer") {puts "Hi"}
使用ruby的yield语法 yield 相当于block的关联调用
无参数:def call_block
puts "method start"
yield
yield
puts "method end"
end
call_block {puts "hi"}
有参数:def call_block
yield("hello",99)
end
call_block {|str,mub| ...}
ruby中有大量使用block实现迭代器
animals = %w(ant bee cat bog elk)
animals.each{|n| puts n}
类似的:5.times {print "*"}
3.upto(6) {|i| print i}
('a'..'e').each{|char| print char}
ruby读写文件
ruby有一个完备的I/O库。输出的方法:除了 puts、 print还有printf
printf(“numer:%5.2f,\nString:%s\n”,1.23,"hello")
# 5.2f 替换一个浮点数,最多5个字符,其中2个在小数点后面 和一个字符串
将输入读入程序中 最传统的方式:使用gets函数
line =gets
print line
2 类、对象和变量
对象可使用 inspect来观察情况
例如:a = Song.new("test","bert") ;puts a.inspect
返回:#<Song:0x373f610 @author="bert", @name="test">
也可以使用to_s来查看 例如:;puts a.to_s
返回:#<Song:0x373f610>
类的继承中 super不使用参数时,ruby向当前对象的父类发送一个消息,要求它调用子类中同名方法。换句话说
super 指定去父类里寻找同名的实例方法来执行。
类中定义属性的方法除了常规以外,还采取:
attr_reader :name,:author
attr_writer :name,:author
attr_xx 实际上以我的理解是 mixin 进来个ruby方法
虚拟属性:dutation_in_minutes就是所谓的虚拟属性--原因是在它内部没有对应的实例变量而已
class Song
def dutation_in_minutes
@dutation/60.0
end
end
类方法的定义:
class Example
def Example.class_method
end
end
单件--单例 和其他构造函数
单例就是一个类只能new出一个对象,不能随便new出其他。因此需要把 类方法:new藏起来而私有化。例如:
class MyLogger
private_class_method :new
@@logger =nil
def MyLogger.create
@@logger = new unless @@logger
@@logger
end
end
通过 MyLogger.create.object_id 返回总是一种结果。
访问控制 Public(除initialize外其默认都是public) 、Protected(必须在类内或其子类中,实例对象可调用---整个家族可访问的)
、Private(不能明确被接受者调用,其接受者只能是当前锁定的self,意味着私有方法只能在对象上下文中调用。)
例如 1: ...
public :method1, :method2
protected :method3
private :method4
例如2:
private
def method
...
end
亲自测试总结:private私有表示这是实例对象的私有方法---该方法不能被接受者调用,在上下文中、继承关系中直接调用,只能在类中。
而protected受保护的表示这是实例的受保护的方法---但这方法必须有接受者调用 a.protected_method() > b.protected_method()
在上下文中、继承以及家族中,受保护的方法不能在外面被调用,只能呆在类中。
变量,不是对象,只是对象的引用。变量保存的是对象的引用,而非对象本身。
赋值别名(alias)对象,就相当于引用同一对象多个变量,但是可以用 String的dup方法避免创建别名,
它会创建一个新的、具有相同内容的String对象 例如
person1 = "Tim" ;person2 = person1.dup; person1[0] ="J"; person1 --> "Jim" person2--> "Tim"
也可以通过冻结一个对象来阻止他人对它的改动,试图更改一个冻结的对象会引发raise一个typeErro异常
person1="Tim" ;person1.freeze
2 容器、Blocks和迭代器
容器是指含有一个或者多个对象的引用的对象。例如歌曲目录和待播放歌曲的目录。
数组:a=[1,2,3,2,9] a[start,count]返回从start开始count个对象的数组 a[-3,2]--> [3,2]
也使用range来索引 a[1..3] -> [2,3,2]
数组还有一些有用的方法,可用数组实现栈(stack)、收集(set)、队列(queue)、双向队列(dequeue)
和先进先出队列(fifo)
散列表 hashes(也称关联数组、图map或者词典)可用任何对象做索引,但是它元素是无序的,很难使用hash来实现栈和队列。
迭代器
class SongList
def with_title(title)
@song.find{|song| title == song.name} #find就是一个迭代器,反复调用block
end
end
关于block和yield的再次研究
def three_times
yield
yield
yield
end
three_times { puts "x"} #block和three_times方法联合在一起调用
例如:
def fib_up_to(max)
i1,i2 =1,1
while i1 <= max
yield i1
i1,i2 =i2,i1+i2
end
end
fib_up_to(22) {|f| print f," "}
结果是1 1 2 3 5 8 13 21
实现迭代器:yield 和block ---{ ...} 和 do ...end
内外迭代器:ruby的迭代器集成与内部,不单单是个方法,每当产生新值就调用yield。
内迭代器不足:当把迭代器看是一个对象的时候(把迭代器传递给一个方法,而该方法需要访问有迭代器返回的每个值时),表现欠佳,
也难实现并行迭代2个收集。
外迭代器:幸运的是ruby 1.8 提供了 Generator库,该库解决了内迭代的不足,实现了外部迭代。
容器很重要,处处是容器---事务Blocks:定义在事务控制环境下,例如打开一个文件后,执行block后 文件自动关闭。
例如 File.open() { ...} 该方法的实现 归咎于 Kernel.block_given?方法的功劳。
Block闭包 :创建proc 对象时,不仅获得了一堆代码还获得了于block关联的上下文 self值、作用域方法、变量和常量。即使Block被
定义的环境消失,Block仍然可使用原始作用域中的信息。例如:
def n_times(t)
return lambda{|n| t*n }
end
p1 = n_times(23)
p1.call(3) --> 69
p2 = n_times("hello ")
p2.call(3) -> "hello hello hello "
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~