- 浏览: 347913 次
- 性别:
- 来自: 福州
文章分类
最新评论
-
18215361994:
chrome扩展中可以获取开发者工具所有资源不?
Chrome 插件开发 -
lBovinl:
完全是一头雾水~o(︶︿︶)o 唉
乱七八糟的Ruby笔记 -
zhangyanan_it:
楼主总结的好多!想问下:map.resources :role ...
Rails随记 -
justin_chiang:
...
Propertiess资源文件的读取和简单的性能测试 -
lezi2012:
感谢分享!!!感谢分享!!!感谢分享!!!感谢分享!!!感谢 ...
Rails随记
全当为了体会Rails的魅力,学学基础Ruby,摘自锄头书,其实这本书的后半本比较精华一些
输出字符串的方法:可以使用puts与print,如果需要带换行,可以在里面加入\n符,可以使用#{}带参数写入字符串中,在1.9中,可以使用p 缩写打印语句(puts, or println)
生成类的实例的方式
ClassName.new(args) ...
命名的一些规范
类定义:
class Name
.....
end
类名必须大写首字母
方法的定义
def methodName
...
end
方法名小写开头
进行方法调用时候,可以忽略()的使用,同样在定义不带参数方法时,也可以不带(), 进行方法调用时,也可以忽略()
因为Ruby是纯粹的面向对象的方法,所以其所有的对象都拥有完全的方法,不像Java的基本类型
ruby class中常用的变量定义方式
局部变量,方法参数,方法名都必须使用小写字母,或者下划线开头
全局变量使用$开头
实例变量使用@开头
类变量使用@@开头
类名,module,构造函数名称均要以一个大写字母开头
一般来说,对于变量名,多使用_下划线的方式进行多字母的组合,而类名使用首字母大写的方式AxxBxx...
Array and Hashes
a=[] //声明一个数组,访问的方式一样使用[index],也可以使用animals = %w( ant bee cat dog elk )
a={"key" => "value"} 用于声明hashes字典 访问的方式[key]
Hash.new(0) //用于创建value默认值为0的hash对象
另外一种字典的定义方式
inst_section = {:cello => 'string'} 使用:key 代替字符串的"key", 也可以使用key:value的1.9新语法
注意访问时,也需要使用对应的hash[:key]
逻辑判断 if...elsif...else...end
也有按照英文语法的
puts "Danger, Will Robinson" if radiation > 3000 //同理可以应用在其他控制流语句之上
正则表达式
使用/...../ 格式进行声明,类似字符串,也是一种单独独立的对象
进行调用的方式. str=~/reg/ 用于判断str是否符合正则的要求,返回boolean值
sub ,替换首个符合的字符串,
gsub,替换所有符合的字符串 //上述均为字符串方法
更多的是使用字符串来调用正则对象
代码块block的使用,用于提供小块可传递的方法
block两种定义的方式:
{puts hello}
do
xxx
end
可以将block作为参数,或者附带在参数后进行传递到方法中
verbose_greet("Dave", "loyal customer") { puts "Hi" }
在方法中,使用yield 调用传入的block块
同理,也可以传递参数给block中
def who_says_what
yield("Dave", "hello")
yield("Andy", "goodbye")
end
who_says_what {|person, phrase| puts "#{person} says #{phrase}" //与groovy中的基本一致
迭代器,用于便捷的输出集合数组
animals.each {|animal| puts animal } //类似groovy中默认的it,对于数字也内置了循环的方法
5.times { print "*" }
3.upto(6) {|i| print i }
('a'..'e').each {|char| print char }
printf,类似StringFormat,或者System.out.printf的方式,使用变量生成所需的字符串
printf("Number: %5.2f,\nString: %s\n", 1.23, "hello") //只是变的更短了
读取IO或者键盘输入的方式
line = gets
print line
对于长篇的文章,需要使用while进行循环多行的读取
当使用命令行执行时,可以使用ARGV 以数组方式获取所附带的参数
initialize 方法,将会在调用class.new方法时被执行,可以通过new传递参数,应该作用与java过得构造函数一样
可以将传入的变量设置为@,实例变量,这里区别Java的方式,不需要在外部声明一个对象,@符号定义的变量,将会在类实例内部共享访问
toString() 方法 to_s(),方法返回的方式与Java类似,只需返回一个字符串,注意使用p和puts打印输出的内容并不相同,前者更详细一些,后者与print一致,只打出对象所在内存位置
对实例变量的访问,默认并不能直接访问@定义的变量,可以通过定义同名方法进行读取
def isbn
@isbn
end
也可以使用简单的 attr_reader属性,用于读取实例变量(只读)
attr_reader :isbn, :price
如果要修改实例变量,可以定义指定格式的方法 =结尾
def price=(new_price)
@price = new_price
end
也可以使用方便的
attr_writer :price
最简单的方式(可读写):
attr_accessor :price
可以将外部可以访问的实例变量成为属性
require 'csv' 用于导入cvs模块
require_relative 'book_in_stock' 用于导入book_in_stock类
[]<< obj 可以使用<< 将一个对象放入数组中
Access Control 访问控制
Ruby中一样有public protected,private 三种访问权限
方法默认都是public,除了initialize方法(始终是private)
设置的方式
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 # so this will be 'public'
#...
end
也可以使用统一定义的方式
public :method1, :method4
protected :method2
private :method3
Ruby中的字符串可以直接通过[index]进行修改字符
Containers, Blocks,and Iterators 容器,块,迭代
Arrays 数组, ruby中允许使用负数索引[-1]...对于空内容,返回nil,
支持区间的访问方式 a[1..3], 等同于a[1,3] 返回索引1到索引3之间的所有元素子数组
也内置了push,pop,shift等方法,用于模拟栈,队列的行为
对于搜索,可以使用fitst,last等方法,寻找指定的内容所在的索引
hash与array都提供了length,用于获取长度
使用字典,判断一个集合中出现的相同内容的次数...将每次的内容作为key存入,然后对值进行+=1操作
继承的使用,注意::前后都不允许有空格
class World < Test::Unit::TestCase
使用Blocks
some_array.each {|value| puts value * 3 } //each循环,可以用于数组和hashes, 注意block中参数设置
也可以使用do..end方式的block定义
other_array.each do |value|
sum += value
puts value / sum
end
注意block中变量的作用域问题,尽量不要在block中使用同名的变量
在1.9中已经修复,但还是建议不要使用与外部方法同名的变量名
与Groovy,对于block的循环,也内置了inject,collect,each等方法
将数组,hash转换成迭代器的方式
a = [ 1, 3, "cat" ]
h = { dog: "canine", fox: "lupine" }
enum_a = a.to_enum
enum_h = h.to_enum
访问的时候,只要调用next方法即可
enum_a.next....
对于迭代器,多了一种循环的方式loop do...end,也可以使用loop{block}到头
short_enum = [1, 2, 3].to_enum
long_enum = ('a'..'z').to_enum
loop do
puts "#{short_enum.next} #{
long_enum.next}"
end
block的方式
v=[13,54,67,32]
ev=v.to_enum
loop {p ev.next}
Enumerators 本身也是一个对象,同样具有一些方法,如从新转换成数组
字符串转换成数组的方式
result = []
"cat".each_char.each_with_index {|item, index| result << [item, index] }
result # => [["c", 0], ["a", 1], ["t", 2]]
同样可以使用block达到一个自动关闭文件的事务处理
class File
def self.open_and_process(*args)
f = File.open(*args)
yield f
f.close()
end
end
在方法的内部,使用常量 if block_given? 可以判断是否附带了block
将block作为对象使用,在方法定义的参数中,使用&name,对传入的block进行捕获,然后可以赋值给变量使用
def pass_in_block(&action)
@stored_proc = action
end
调用的时候,使用@stored_proc.call(parameter)
另外一种声明block的方式---lamba
bo = lambda { |param| puts "You called me with #{param}" }
调用的方式一样使用call
bo.call 99
closure闭包的实现,使用方法中返回的lamba,达到闭包的效果
def n_times(thing)
lambda {|n| thing * n }
end
p1 = n_times(23)
p1.call(3) # => 69
ruby1.9中创建lamba新的方式
->params { ... } 格式
proc1 = ->arg { puts "In proc1 with #{arg}" }
调用的方式
proc1.call "ant" , 其中可以带多个参数
在定义lamba,或者->时, 也可以定义多种不同的参数,包括*arg,可变数量参数,&block
Ruby中,使用< 来实现简单的继承,同Java一样,类默认都继承Object,在1.9中,修改为BasicObject
对弗雷方法的调用,一样使用super
在ruby中,引入module,用于提供一个命名空间的方式去保存一些对象(class,method)等
需要注意的是这里的命名规则
module Model // 首字母大写
VAB=1 // 定义model内的常量
requeire "model"//在被引用时,首字母需要小写
Model::VAB,引用model中的常量
Model.metho()// 使用module内的方法
对于引入的class,require时,可以忽略大小写,当时在使用时.就必须使用首字母大写
module的使用比较特殊一些,用于将一种包装好的对象,直接include进入方法,就可以直接在类的内部附带了这些方法,有些类似Java的 static import,静态导入
概念上使用混编的方式,为类提供继承之外的选择,又区别与Java中的组合,更便利的组合了方法的使用,无需自己重新为类添加方法体---完善了接口的工作
没有经过测试,当可以使用module保存一个全局变量,供其他类中进行共享,如果需要进行区分,可以使用object_id,来实现唯一的操作
def state=(value)
State[object_id] = value
end
如果方法中出现了多个同名的方法,Ruby会有自己一套的策略
如果是继承的父类中拥有多个方法,那个将会使用第一个继承的类
如果是多个导入模块之间存在重复命名的方法,那么将会采用最后一个找到的方法
Numbers
Integer 整型内主要包含Fixnum,Bignum两种类型的数字,当数字的大小超过Fixnum后,会自动进行转换
其他类型还有Complex,Rational,Float,Numeric
常用的数字循环有
3.times { print "X " }
1.upto(5) {|i| print i, " " }
99.downto(95) {|i| print i, " " }
50.step(80, 5) {|i| print i, " " }
Strings
可以使用""或''进行声明,使用的时候注意,\进行转义,使用的方式与其他语言类似
#{} 用于在字符串中插入Ruby语句,可以是变量,也可以是方法,也包括全局 变量
"This is line #$." # => This is line 3
%Q{...},%Q!...!,%q/.../ 也都可以用于包含字符生成字符串,代替"",主要作用是免去\转义,同样可以在里面使用#{}
同Python一样,可以在文件头部声明#encoding: utf8 来指定编码,使用str.encoding 得到指定字符的编码
简单的使用正则的方式
c="123 1231 23s68 1628"
ob=c.scan(/\d+/)
Range 区间.类似Python中的定义
常见的定义方式
1..9
'a'..'z'
可以使用to_a,to_enum等方法转换成所需的类型
常见的一些方法使用
digits = 0..9
digits.include?(5) # => true
digits.min # => 0
digits.max # => 9
digits.reject {|i| i < 5 } # => [5, 6, 7, 8, 9]
digits.inject(:+) # => 45
可以通过定义两个方法,来对自定义的类添加Range的特性
def <=>(other)
@value <=> other.value
end
def succ
PowerOfTwo.new(@value + @value)
end
也可以将Range作为条件区间使用
while line = gets
puts line if line =~ /start/ .. line =~ /end/ ..//用于读取中在指定区间之间的内容,类似< ,>的使用
end
Range也可以使用===来进行判断对象是否保存在该区间内
(1..10) === 5 # => true ,对浮点一样有效
..两个点与...三个点定义的区分, ..包括了后面数的,而...不包括<=与<的区别
Regular Expressions 正则表达式的使用
在ruby中的正则使用,字符串或者正则都可以调用对付进行匹配
1:匹配方法
=~ 用于匹配字符,并返回符合的字符所在索引
2:替换方法
str.sub(/pattern/,"value") 类似replace方法,返回修改的内容,同样不对原内容进行修改
gsub.. replaceAll的实现
如果需要直接修改原内容,可以使用带!版本的sub方法
str.sub!(/i/, "*")
str.gsub!(/t/, "T")
三种创建正则的方式
/pattern/ , Regexp.new("pattern"),%r{mm/dd}
得到模式匹配的内容,
pattern.match("str")进行内容匹配,以数组的形式返回匹配结果
\h用于匹配hex字符
\s用于匹配一些空格,换行,制表符等
ruby下还提供了一些[:space:]类似的方法,对一些常见的规则进行了封装.这里忽略
ruby还提供了一种是用key的方式,将捕获的内容直接生成变量
/(?<hour>\d\d):(?<min>\d\d)(..)/ =~ "12:50am" 类似以前的$1等方式,
读取时候使用"Hour is #{hour}, minute #{min}"
$的读取方式,对reg中的()分组进行读取,当采用上面的方法会更简单一些
/(\d\d):(\d\d)(..)/ =~ "12:50am" # => 0
"Hour is #$1, minute #$2" # => "Hour is 12, minute 50"
动态替换字符
1:使用sub配合{}闭包对匹配的结果进行处理,让结果可以动态变化
a = "quick brown fox"
a.sub(/^./) {|match| match.upcase } # => "Quick brown fox"
a.gsub(/[aeiou]/) {|vowel| vowel.upcase } # => "qUIck brOwn fOx"
2:使用&;方法,快速处理结果
name.downcase.gsub(/\b\w/, &:upcase)
3:使用hash方式,使用key-value,对匹配的字符进行处理,注意默认值的使用
replacement = { "cat" => "feline", "dog" => "canine" }
replacement.default = "unknown"
"cat and dog".gsub(/\w+/, replacement) # => "feline unknown canine"
对匹配的字符,使用\index的引用方式,索引由1开始
也可以\k<name>的方式进行读取,同使用\?<>方式一样
非捕获分组
(?:....) ,这样就不会保存该分组结果
匹配规则强化...
后匹配 (?=...) 表示其中的内容必须存在,当不捕获
前匹配(?<=...)后面内容必须存在
(?!O) // 设置为非捕获排除O
(?>O) //进行严格匹配的设置,不截取部分 也可以写成(O++)
控制回溯
用于控制懒惰和贪婪的搜索模式,默认为贪婪,可以通过设置(?>),设置为懒惰
其他太麻烦...不做记录
More About Methods
Ruby中比较特殊的方式,使用?,=,!在方法名后进行了定义
当方法返回一个Boolean值时,常用?在结尾进行声明
当方法可能造成危险时,常用!在结尾进行声明
当方法设置值的时候,使用=进行声明
如同Python一样,也可以给方法的参数设置默认值
def method(arg="orz"...)
也可以通过第一个参数,动态生成第二个参数的默认值
def surround(word, pad_width=word.length/2)
可变参数列表
def varargs(arg1, *rest) //同Python一样,Java中定义的方式 type...args
也可以直接使用(*)设置可变参数
对于处于参数列表中间的*,也会按照参数长度进行自动匹配....
ruby中的方法调用,并不要求()的使用, 同Python一样,不需要使用return,即可对方法返回参数,
使用return时,可以用于返回多个结果
进行参数传递时,使用method(*(a),b) 其中的*()用于将里面的参数自动拆转成所需的参数列表值
Expressions 表达式
因为Ruby是完全面向对象,所以与Java区别,没有基本类型的限制,其基本类型也是对象,同样提供了多种方法
可以通过重载运算符,为自定义类添加便捷的操作方式
def <<(score)
@total_score += score
@count += 1
self //返回本身
end
甚至可以扩展方法名为[],为对象添加类似数组的方式,其实是一个方法调用
def [](p1, p2, p3)
end
如果要实现任意多个参数,注意使用*
def []=(*params)
end
Ruby中存在不少语法糖的用法
a = 1, 2, 3, 4 # a=[1, 2, 3, 4]
c, = 1, 2, 3, 4 # c=1
a, *b = 1, 2, 3 # a=1, b=[2, 3]
a, (b,*c), d = 1,[2,3,4],5 # a=1, b=2, c=[3, 4], d=5
注意ruby中不存在Java中的++操作,可以使用+=替换,在进行方法重载是也是
与Javascript类似,ruby中将nil都可以当做false使用,而非空的都当做true,
同样也可以使用&& , || 对两个值进行选择
defined? 用于返回后面所带参数的类型
可以在自定义类中重载==方法用于进行比较, 同样也可以扩展!=方法
def ==(other)
end
ruby中的if...then..eleif...then...else 就是多了then,可以在一行中进行操作
比起Java,ruby中可以使用unless...进行if的反操作
switch的代替
case
when song.name == "Misty"
puts "Not again!"
when song.duration > 120
puts "Too long!"
when Time.now.hour > 21
puts "It's too late"
else
song.play
end
Loops循环
while 循环与Java一致
until 循环与while反作用
Iterators 迭代 多用于与block组合使用
3.times //...
0.upto(9) //..
0.step(12, 3) // 0-12 每次前进3
[ 1, 1, 2, 3, 5 ].each{} //迭代
执行文件操作时,可以使用File.open("ordinal").grep{...} 进行迭代
与Java中的类似,可以使用for...in的循环方式
for obj in array
...
end
也可以使用
array.each do |song|
song.play
end
可以通过在自定类中重载each方法来实现自定义循环方式
loop {} 循环 ,需要使用break跳出循环
Break, Redo, and Next 的使用
与Java相比,应该就是多了一个Redo
异常处理
完整的异常监听
require 'openuri'
page = "podcasts"
file_name = "#{page}.html"
web_page = open("http://pragprog.com/#{page}")
output = File.open(file_name, "w")
begin //开始监听
while line = web_page.gets
output.puts line
end
output.close
rescue Exception //catch异常
STDERR.puts "Failed to download #{page}: #{$!}"
output.close
File.delete(file_name)
raise //再次抛出异常
end
简单的方式
begin
eval string
rescue SyntaxError, NameError => boom //同时捕获多个异常,并进行重命名对象
print "String doesn't compile: " + boom
rescue StandardError => bang
print "Error running script: " + bang
ensure //类似finally
f.close
end
retry 可以用于在异常后,重新执行begin内的语句
raise ... 用于抛出异常,与throw一样
异常捕获的另外一种形式
catch(:done) do......的使用 将可能发生的异常封装在变量内进行返回,内容可以通过throw 进行抛出
word_list = File.open("wordlist")
word_in_error = catch(:done) do
result = []
while line = word_list.gets
word = line.chomp
throw(:done, word) unless word =~ /^\w+$/
result << word
end
puts result.reverse
end
if word_in_error
puts "Failed: '#{word_in_error}' found, but a word was expected"
end
也可以使用throw :arg 进行一个异常信息的抛出
Basic Input and Output IO操作
使用File对象进行对本地文件的操作
File.open("testfile", "r") {} 使用block可以达到自动关闭的效果
File.new() 可以用于创建新文件
读取文件操作
File.open("testfile") do |file|
while line = file.gets
puts line
end
end
也可以使用静态的IO方法进行读取
IO.foreach("testfile") {|line| puts line }
也可以按照数组的方式进行读取
arr = IO.readlines("testfile")
arr.length # => 4
arr[0] # => "This is line one\n"
如果要写入文件,需要在打开文件的参数中附加上"w"权限
File.open("output.txt", "w") do |file|
file.puts "Hello"
file.puts "1 + 2 = #{1+2}" //写入
end
puts File.read("output.txt") //读取
也可以使用<< 的方式将内容写入文件
Talking to Networks 与网络进行IO操作
Socket操作
require 'socket'
client = TCPSocket.open('127.0.0.1', 'finger')
client.send("mysql\n", 0) # 0 means standard packet
puts client.readlines
client.close
更高级的Http连接
require 'net/http'
h = Net::HTTP.new('www.pragprog.com', 80)
response = h.get('/titles/ruby3/programmingruby3')
if response.message == "OK"
puts response.body.scan(/<img alt=".*?" src="(.*?)"/m).uniq
end
也可以使用open-uri类库
require 'openuri'
open('http://pragprog.com') do |f|
puts f.read.scan(/<img alt=".*?" src="(.*?)"/m).uniq
end
会自动对url不同进行处理
Fibers, Threads,and Processes
Fiber 在ruby1.9中新增纤程
Fiber 用于将元素保存在一个临时的Fiber中,然后进行返回
words = Fiber.new {
Fiber.yield word.downcase
}
读取的时候.使用resume方法 返回源对象
读取的时候使用类似迭代的对象进行读取操作
更完整的解释应该是,将对象放入指定小线程中执行,使用resume得到结果 (异步)
创建多线程的方式
Thread.new(args){block} 的方式创建新的线程 ,返回线程对象
可以使用该对象的join进入该线程,也可以是执行该线程
sleep(rand(0.1)) 用于在线程体中进行休眠, rand用于生成0-1之间的小数
Thread.abort_on_exception = true 用于在执行线程时,忽略异常处理
Ruby中同步的方式
mutex.lock #### 锁定线程
sum = inc(sum) # one at a time, please
mutex.unlock ####
也可以使用block的方式,自动解锁
mutex.synchronize do ####
sum = inc(sum) # one at a time, please
end ####
Mutex.new本身也是对象,需要新建后使用,还提供了sleep等方法
Unit Testing
简单的创建一个单元测试类
require 'test/unit'
class TestRoman < MiniTest::Unit::TestCase
def test_simple
assert_equal("i", Roman.new(1).to_s)
assert_equal("ix", Roman.new(9).to_s)
end
end
也可以继承Test模块
class TestRoman < Test::Unit::TestCase
注意命名规则
Test作为类名开头
test_作为方法开头
可以使用 require 'dbi 进行包含数据库连接的测试
对于Class中定义的SRT=xx 这样的变量, 可以在外部使用Class::SRT进行访问, 类似Java中的静态变量
:: 也可以用于访问Module中的Class类型,然后进行实例化使用
设置源代码 编码
# coding: utf8 或# encoding: ascii
对字符进行编码转换
str= ole_str_utf.encode("iso88591")
在打开文件时,也可以通过附带参数,使用指定编码访问文件
f = File.open("iso88591.txt", "r:iso88591")
也可以组合使用读取,和输出使用不同的编码
f = File.open("iso88591.txt", "r:iso88591:utf8")
the first is the external encoding, and the second is the internal encoding.
读取二进制文件的方法
f = File.open("iso88591.txt", "rb")
使用cgi.rb 可以搭建基于CGI的网络应用
Haml and erb/eruby, 用于生成HTML的模板
如果需要生成XHTML或者xml,可以使用Builder
Haml更多的使用在内嵌的代码中生成HTML
erb,更多的使用模板文件进行生成文件,当然也可以嵌入使用
Ruby and Microsoft Windows
Ruby提供了丰富的操作Windows Api的类库
如 使用Email打开指定网页
require 'win32ole'
ie = WIN32OLE.new('InternetExplorer.Application')
ie.visible = true
ie.navigate("http://www.pragprog.com")
生成新的Excel文件
excel = WIN32OLE.new("excel.application")
Ruby中包含了一些变量,用于保存特定情况下的信息
$! 异常信息
$@ 异常抛出的堆栈信息
names = %{ant bee cat}
result = names.map(&:upcase)
这里的&:使用比较特殊,需要研究一下,现在运行出错
在Ruby的class中提供了self对象,作用与Java中的this类似
定义静态方法的方式,在定义方法名时,使用self.MethodName, 或 ClassName.MethodName进行定义
调用就可以直接使用ClassName.methodname进行直接调用
其他的方式访问单例对象 ,定义类时
classname="" // 必须定义一个字符串 ,这样在类中使用self时,就会变成这里的赋值
class << className ,这样内部的方法就可以直接使用class调用
<<定义类的方式应用比较多一些,也可以作为变量返回.也可以用于暴露出特定的变量提供使用Class进行修改(乱)
class Test
@var = 99
class << self
attr_accessor :var
end
end
这样就可以通过Test.var对实例变量进行修改
在Ruby中可以通过在子类中,修改父类的方法访问级别,将private的方法变成public的方法
其实就是通过重载方法,然后在子类中调用super //这里也比Java简单了,直接在方法体中调用super,就可以执行父类中的同名方法
对模块的继承 extend
module Humor
def tickle
"#{self} says hee, hee!"
end
end
obj = "Grouchy"
obj.extend Humor
puts obj.tickle
也可以在类中使用
class Grouchy
extend Humor
end
puts Grouchy.tickle
include主要用来将一个模块插入(mix)到一个类或者其它模块。
extend 用来在一个对象(object,或者说是instance)中引入一个模块,这个类从而也具备了这个模块的方法。
使用的三种情况
在类中include模块,使模块中的方法成为类的实例方法
在类定义中extend模块,使模块中的方法成为类的类方法
实例方法和类方法的区别,就如同非静态方法,与静态方法的区别
Struct, 类似c中的struct, 可以用于便捷的创建class级别对象,
Person = Struct.new(:name, :address, :likes) //参数中的应该是实例变量,也可以作为构造函数动态传入
dave = Person.new('Dave', 'TX')
dave.likes = "Programming Languages"
puts dave
重写该类中的方法
Person = Struct.new(:name, :address, :likes)
class Person
def to_s
"#{self.name} lives in #{self.address} and likes #{self.likes}"
end
end
也可以写成另外中形式,更利于阅读一些
class Person < Struct.new(:name, :address, :likes)
def to_s
"#{self.name} lives in #{self.address} and likes #{self.likes}"
end
end
动态的创建类的另外一种方式,可以使用block对类的方法进行定义
some_class = Class.new do
def self.class_method
puts "In class method"
end
def instance_method
puts "In instance method"
end
end
some_class.class_method
obj = some_class.new
obj.instance_method
instance_eval and class_eval 也可以用动态创建类
"cat".instance_eval do //使用block的方式
puts "Upper case = #{upcase}"
puts "Length is #{self.length}"
end
也可以使用参数传递的方式
"cat".instance_eval('puts "Upper=#{upcase}, length=#{self.length}"')
class_evel的使用,为已存在的类添加实例方法
class MyClass
end
MyClass.class_eval do
def instance_method
puts "In an instance method"
end
end
而对已存在的class调用instance_eval,而是添加类方法,也是使用block进行传递
可以在Ruby的class类中,实现一些Hook方法,用于在类调用时,发生的一些事件进行回调,如果方法未定义,参数错误等
输出字符串的方法:可以使用puts与print,如果需要带换行,可以在里面加入\n符,可以使用#{}带参数写入字符串中,在1.9中,可以使用p 缩写打印语句(puts, or println)
生成类的实例的方式
ClassName.new(args) ...
命名的一些规范
类定义:
class Name
.....
end
类名必须大写首字母
方法的定义
def methodName
...
end
方法名小写开头
进行方法调用时候,可以忽略()的使用,同样在定义不带参数方法时,也可以不带(), 进行方法调用时,也可以忽略()
因为Ruby是纯粹的面向对象的方法,所以其所有的对象都拥有完全的方法,不像Java的基本类型
ruby class中常用的变量定义方式
局部变量,方法参数,方法名都必须使用小写字母,或者下划线开头
全局变量使用$开头
实例变量使用@开头
类变量使用@@开头
类名,module,构造函数名称均要以一个大写字母开头
一般来说,对于变量名,多使用_下划线的方式进行多字母的组合,而类名使用首字母大写的方式AxxBxx...
Array and Hashes
a=[] //声明一个数组,访问的方式一样使用[index],也可以使用animals = %w( ant bee cat dog elk )
a={"key" => "value"} 用于声明hashes字典 访问的方式[key]
Hash.new(0) //用于创建value默认值为0的hash对象
另外一种字典的定义方式
inst_section = {:cello => 'string'} 使用:key 代替字符串的"key", 也可以使用key:value的1.9新语法
注意访问时,也需要使用对应的hash[:key]
逻辑判断 if...elsif...else...end
也有按照英文语法的
puts "Danger, Will Robinson" if radiation > 3000 //同理可以应用在其他控制流语句之上
正则表达式
使用/...../ 格式进行声明,类似字符串,也是一种单独独立的对象
进行调用的方式. str=~/reg/ 用于判断str是否符合正则的要求,返回boolean值
sub ,替换首个符合的字符串,
gsub,替换所有符合的字符串 //上述均为字符串方法
更多的是使用字符串来调用正则对象
代码块block的使用,用于提供小块可传递的方法
block两种定义的方式:
{puts hello}
do
xxx
end
可以将block作为参数,或者附带在参数后进行传递到方法中
verbose_greet("Dave", "loyal customer") { puts "Hi" }
在方法中,使用yield 调用传入的block块
同理,也可以传递参数给block中
def who_says_what
yield("Dave", "hello")
yield("Andy", "goodbye")
end
who_says_what {|person, phrase| puts "#{person} says #{phrase}" //与groovy中的基本一致
迭代器,用于便捷的输出集合数组
animals.each {|animal| puts animal } //类似groovy中默认的it,对于数字也内置了循环的方法
5.times { print "*" }
3.upto(6) {|i| print i }
('a'..'e').each {|char| print char }
printf,类似StringFormat,或者System.out.printf的方式,使用变量生成所需的字符串
printf("Number: %5.2f,\nString: %s\n", 1.23, "hello") //只是变的更短了
读取IO或者键盘输入的方式
line = gets
print line
对于长篇的文章,需要使用while进行循环多行的读取
当使用命令行执行时,可以使用ARGV 以数组方式获取所附带的参数
initialize 方法,将会在调用class.new方法时被执行,可以通过new传递参数,应该作用与java过得构造函数一样
可以将传入的变量设置为@,实例变量,这里区别Java的方式,不需要在外部声明一个对象,@符号定义的变量,将会在类实例内部共享访问
toString() 方法 to_s(),方法返回的方式与Java类似,只需返回一个字符串,注意使用p和puts打印输出的内容并不相同,前者更详细一些,后者与print一致,只打出对象所在内存位置
对实例变量的访问,默认并不能直接访问@定义的变量,可以通过定义同名方法进行读取
def isbn
@isbn
end
也可以使用简单的 attr_reader属性,用于读取实例变量(只读)
attr_reader :isbn, :price
如果要修改实例变量,可以定义指定格式的方法 =结尾
def price=(new_price)
@price = new_price
end
也可以使用方便的
attr_writer :price
最简单的方式(可读写):
attr_accessor :price
可以将外部可以访问的实例变量成为属性
require 'csv' 用于导入cvs模块
require_relative 'book_in_stock' 用于导入book_in_stock类
[]<< obj 可以使用<< 将一个对象放入数组中
Access Control 访问控制
Ruby中一样有public protected,private 三种访问权限
方法默认都是public,除了initialize方法(始终是private)
设置的方式
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 # so this will be 'public'
#...
end
也可以使用统一定义的方式
public :method1, :method4
protected :method2
private :method3
Ruby中的字符串可以直接通过[index]进行修改字符
Containers, Blocks,and Iterators 容器,块,迭代
Arrays 数组, ruby中允许使用负数索引[-1]...对于空内容,返回nil,
支持区间的访问方式 a[1..3], 等同于a[1,3] 返回索引1到索引3之间的所有元素子数组
也内置了push,pop,shift等方法,用于模拟栈,队列的行为
对于搜索,可以使用fitst,last等方法,寻找指定的内容所在的索引
hash与array都提供了length,用于获取长度
使用字典,判断一个集合中出现的相同内容的次数...将每次的内容作为key存入,然后对值进行+=1操作
继承的使用,注意::前后都不允许有空格
class World < Test::Unit::TestCase
使用Blocks
some_array.each {|value| puts value * 3 } //each循环,可以用于数组和hashes, 注意block中参数设置
也可以使用do..end方式的block定义
other_array.each do |value|
sum += value
puts value / sum
end
注意block中变量的作用域问题,尽量不要在block中使用同名的变量
在1.9中已经修复,但还是建议不要使用与外部方法同名的变量名
与Groovy,对于block的循环,也内置了inject,collect,each等方法
将数组,hash转换成迭代器的方式
a = [ 1, 3, "cat" ]
h = { dog: "canine", fox: "lupine" }
enum_a = a.to_enum
enum_h = h.to_enum
访问的时候,只要调用next方法即可
enum_a.next....
对于迭代器,多了一种循环的方式loop do...end,也可以使用loop{block}到头
short_enum = [1, 2, 3].to_enum
long_enum = ('a'..'z').to_enum
loop do
puts "#{short_enum.next} #{
long_enum.next}"
end
block的方式
v=[13,54,67,32]
ev=v.to_enum
loop {p ev.next}
Enumerators 本身也是一个对象,同样具有一些方法,如从新转换成数组
字符串转换成数组的方式
result = []
"cat".each_char.each_with_index {|item, index| result << [item, index] }
result # => [["c", 0], ["a", 1], ["t", 2]]
同样可以使用block达到一个自动关闭文件的事务处理
class File
def self.open_and_process(*args)
f = File.open(*args)
yield f
f.close()
end
end
在方法的内部,使用常量 if block_given? 可以判断是否附带了block
将block作为对象使用,在方法定义的参数中,使用&name,对传入的block进行捕获,然后可以赋值给变量使用
def pass_in_block(&action)
@stored_proc = action
end
调用的时候,使用@stored_proc.call(parameter)
另外一种声明block的方式---lamba
bo = lambda { |param| puts "You called me with #{param}" }
调用的方式一样使用call
bo.call 99
closure闭包的实现,使用方法中返回的lamba,达到闭包的效果
def n_times(thing)
lambda {|n| thing * n }
end
p1 = n_times(23)
p1.call(3) # => 69
ruby1.9中创建lamba新的方式
->params { ... } 格式
proc1 = ->arg { puts "In proc1 with #{arg}" }
调用的方式
proc1.call "ant" , 其中可以带多个参数
在定义lamba,或者->时, 也可以定义多种不同的参数,包括*arg,可变数量参数,&block
Ruby中,使用< 来实现简单的继承,同Java一样,类默认都继承Object,在1.9中,修改为BasicObject
对弗雷方法的调用,一样使用super
在ruby中,引入module,用于提供一个命名空间的方式去保存一些对象(class,method)等
需要注意的是这里的命名规则
module Model // 首字母大写
VAB=1 // 定义model内的常量
requeire "model"//在被引用时,首字母需要小写
Model::VAB,引用model中的常量
Model.metho()// 使用module内的方法
对于引入的class,require时,可以忽略大小写,当时在使用时.就必须使用首字母大写
module的使用比较特殊一些,用于将一种包装好的对象,直接include进入方法,就可以直接在类的内部附带了这些方法,有些类似Java的 static import,静态导入
概念上使用混编的方式,为类提供继承之外的选择,又区别与Java中的组合,更便利的组合了方法的使用,无需自己重新为类添加方法体---完善了接口的工作
没有经过测试,当可以使用module保存一个全局变量,供其他类中进行共享,如果需要进行区分,可以使用object_id,来实现唯一的操作
def state=(value)
State[object_id] = value
end
如果方法中出现了多个同名的方法,Ruby会有自己一套的策略
如果是继承的父类中拥有多个方法,那个将会使用第一个继承的类
如果是多个导入模块之间存在重复命名的方法,那么将会采用最后一个找到的方法
Numbers
Integer 整型内主要包含Fixnum,Bignum两种类型的数字,当数字的大小超过Fixnum后,会自动进行转换
其他类型还有Complex,Rational,Float,Numeric
常用的数字循环有
3.times { print "X " }
1.upto(5) {|i| print i, " " }
99.downto(95) {|i| print i, " " }
50.step(80, 5) {|i| print i, " " }
Strings
可以使用""或''进行声明,使用的时候注意,\进行转义,使用的方式与其他语言类似
#{} 用于在字符串中插入Ruby语句,可以是变量,也可以是方法,也包括全局 变量
"This is line #$." # => This is line 3
%Q{...},%Q!...!,%q/.../ 也都可以用于包含字符生成字符串,代替"",主要作用是免去\转义,同样可以在里面使用#{}
同Python一样,可以在文件头部声明#encoding: utf8 来指定编码,使用str.encoding 得到指定字符的编码
简单的使用正则的方式
c="123 1231 23s68 1628"
ob=c.scan(/\d+/)
Range 区间.类似Python中的定义
常见的定义方式
1..9
'a'..'z'
可以使用to_a,to_enum等方法转换成所需的类型
常见的一些方法使用
digits = 0..9
digits.include?(5) # => true
digits.min # => 0
digits.max # => 9
digits.reject {|i| i < 5 } # => [5, 6, 7, 8, 9]
digits.inject(:+) # => 45
可以通过定义两个方法,来对自定义的类添加Range的特性
def <=>(other)
@value <=> other.value
end
def succ
PowerOfTwo.new(@value + @value)
end
也可以将Range作为条件区间使用
while line = gets
puts line if line =~ /start/ .. line =~ /end/ ..//用于读取中在指定区间之间的内容,类似< ,>的使用
end
Range也可以使用===来进行判断对象是否保存在该区间内
(1..10) === 5 # => true ,对浮点一样有效
..两个点与...三个点定义的区分, ..包括了后面数的,而...不包括<=与<的区别
Regular Expressions 正则表达式的使用
在ruby中的正则使用,字符串或者正则都可以调用对付进行匹配
1:匹配方法
=~ 用于匹配字符,并返回符合的字符所在索引
2:替换方法
str.sub(/pattern/,"value") 类似replace方法,返回修改的内容,同样不对原内容进行修改
gsub.. replaceAll的实现
如果需要直接修改原内容,可以使用带!版本的sub方法
str.sub!(/i/, "*")
str.gsub!(/t/, "T")
三种创建正则的方式
/pattern/ , Regexp.new("pattern"),%r{mm/dd}
得到模式匹配的内容,
pattern.match("str")进行内容匹配,以数组的形式返回匹配结果
\h用于匹配hex字符
\s用于匹配一些空格,换行,制表符等
ruby下还提供了一些[:space:]类似的方法,对一些常见的规则进行了封装.这里忽略
ruby还提供了一种是用key的方式,将捕获的内容直接生成变量
/(?<hour>\d\d):(?<min>\d\d)(..)/ =~ "12:50am" 类似以前的$1等方式,
读取时候使用"Hour is #{hour}, minute #{min}"
$的读取方式,对reg中的()分组进行读取,当采用上面的方法会更简单一些
/(\d\d):(\d\d)(..)/ =~ "12:50am" # => 0
"Hour is #$1, minute #$2" # => "Hour is 12, minute 50"
动态替换字符
1:使用sub配合{}闭包对匹配的结果进行处理,让结果可以动态变化
a = "quick brown fox"
a.sub(/^./) {|match| match.upcase } # => "Quick brown fox"
a.gsub(/[aeiou]/) {|vowel| vowel.upcase } # => "qUIck brOwn fOx"
2:使用&;方法,快速处理结果
name.downcase.gsub(/\b\w/, &:upcase)
3:使用hash方式,使用key-value,对匹配的字符进行处理,注意默认值的使用
replacement = { "cat" => "feline", "dog" => "canine" }
replacement.default = "unknown"
"cat and dog".gsub(/\w+/, replacement) # => "feline unknown canine"
对匹配的字符,使用\index的引用方式,索引由1开始
也可以\k<name>的方式进行读取,同使用\?<>方式一样
非捕获分组
(?:....) ,这样就不会保存该分组结果
匹配规则强化...
后匹配 (?=...) 表示其中的内容必须存在,当不捕获
前匹配(?<=...)后面内容必须存在
(?!O) // 设置为非捕获排除O
(?>O) //进行严格匹配的设置,不截取部分 也可以写成(O++)
控制回溯
用于控制懒惰和贪婪的搜索模式,默认为贪婪,可以通过设置(?>),设置为懒惰
其他太麻烦...不做记录
More About Methods
Ruby中比较特殊的方式,使用?,=,!在方法名后进行了定义
当方法返回一个Boolean值时,常用?在结尾进行声明
当方法可能造成危险时,常用!在结尾进行声明
当方法设置值的时候,使用=进行声明
如同Python一样,也可以给方法的参数设置默认值
def method(arg="orz"...)
也可以通过第一个参数,动态生成第二个参数的默认值
def surround(word, pad_width=word.length/2)
可变参数列表
def varargs(arg1, *rest) //同Python一样,Java中定义的方式 type...args
也可以直接使用(*)设置可变参数
对于处于参数列表中间的*,也会按照参数长度进行自动匹配....
ruby中的方法调用,并不要求()的使用, 同Python一样,不需要使用return,即可对方法返回参数,
使用return时,可以用于返回多个结果
进行参数传递时,使用method(*(a),b) 其中的*()用于将里面的参数自动拆转成所需的参数列表值
Expressions 表达式
因为Ruby是完全面向对象,所以与Java区别,没有基本类型的限制,其基本类型也是对象,同样提供了多种方法
可以通过重载运算符,为自定义类添加便捷的操作方式
def <<(score)
@total_score += score
@count += 1
self //返回本身
end
甚至可以扩展方法名为[],为对象添加类似数组的方式,其实是一个方法调用
def [](p1, p2, p3)
end
如果要实现任意多个参数,注意使用*
def []=(*params)
end
Ruby中存在不少语法糖的用法
a = 1, 2, 3, 4 # a=[1, 2, 3, 4]
c, = 1, 2, 3, 4 # c=1
a, *b = 1, 2, 3 # a=1, b=[2, 3]
a, (b,*c), d = 1,[2,3,4],5 # a=1, b=2, c=[3, 4], d=5
注意ruby中不存在Java中的++操作,可以使用+=替换,在进行方法重载是也是
与Javascript类似,ruby中将nil都可以当做false使用,而非空的都当做true,
同样也可以使用&& , || 对两个值进行选择
defined? 用于返回后面所带参数的类型
可以在自定义类中重载==方法用于进行比较, 同样也可以扩展!=方法
def ==(other)
end
ruby中的if...then..eleif...then...else 就是多了then,可以在一行中进行操作
比起Java,ruby中可以使用unless...进行if的反操作
switch的代替
case
when song.name == "Misty"
puts "Not again!"
when song.duration > 120
puts "Too long!"
when Time.now.hour > 21
puts "It's too late"
else
song.play
end
Loops循环
while 循环与Java一致
until 循环与while反作用
Iterators 迭代 多用于与block组合使用
3.times //...
0.upto(9) //..
0.step(12, 3) // 0-12 每次前进3
[ 1, 1, 2, 3, 5 ].each{} //迭代
执行文件操作时,可以使用File.open("ordinal").grep{...} 进行迭代
与Java中的类似,可以使用for...in的循环方式
for obj in array
...
end
也可以使用
array.each do |song|
song.play
end
可以通过在自定类中重载each方法来实现自定义循环方式
loop {} 循环 ,需要使用break跳出循环
Break, Redo, and Next 的使用
与Java相比,应该就是多了一个Redo
异常处理
完整的异常监听
require 'openuri'
page = "podcasts"
file_name = "#{page}.html"
web_page = open("http://pragprog.com/#{page}")
output = File.open(file_name, "w")
begin //开始监听
while line = web_page.gets
output.puts line
end
output.close
rescue Exception //catch异常
STDERR.puts "Failed to download #{page}: #{$!}"
output.close
File.delete(file_name)
raise //再次抛出异常
end
简单的方式
begin
eval string
rescue SyntaxError, NameError => boom //同时捕获多个异常,并进行重命名对象
print "String doesn't compile: " + boom
rescue StandardError => bang
print "Error running script: " + bang
ensure //类似finally
f.close
end
retry 可以用于在异常后,重新执行begin内的语句
raise ... 用于抛出异常,与throw一样
异常捕获的另外一种形式
catch(:done) do......的使用 将可能发生的异常封装在变量内进行返回,内容可以通过throw 进行抛出
word_list = File.open("wordlist")
word_in_error = catch(:done) do
result = []
while line = word_list.gets
word = line.chomp
throw(:done, word) unless word =~ /^\w+$/
result << word
end
puts result.reverse
end
if word_in_error
puts "Failed: '#{word_in_error}' found, but a word was expected"
end
也可以使用throw :arg 进行一个异常信息的抛出
Basic Input and Output IO操作
使用File对象进行对本地文件的操作
File.open("testfile", "r") {} 使用block可以达到自动关闭的效果
File.new() 可以用于创建新文件
读取文件操作
File.open("testfile") do |file|
while line = file.gets
puts line
end
end
也可以使用静态的IO方法进行读取
IO.foreach("testfile") {|line| puts line }
也可以按照数组的方式进行读取
arr = IO.readlines("testfile")
arr.length # => 4
arr[0] # => "This is line one\n"
如果要写入文件,需要在打开文件的参数中附加上"w"权限
File.open("output.txt", "w") do |file|
file.puts "Hello"
file.puts "1 + 2 = #{1+2}" //写入
end
puts File.read("output.txt") //读取
也可以使用<< 的方式将内容写入文件
Talking to Networks 与网络进行IO操作
Socket操作
require 'socket'
client = TCPSocket.open('127.0.0.1', 'finger')
client.send("mysql\n", 0) # 0 means standard packet
puts client.readlines
client.close
更高级的Http连接
require 'net/http'
h = Net::HTTP.new('www.pragprog.com', 80)
response = h.get('/titles/ruby3/programmingruby3')
if response.message == "OK"
puts response.body.scan(/<img alt=".*?" src="(.*?)"/m).uniq
end
也可以使用open-uri类库
require 'openuri'
open('http://pragprog.com') do |f|
puts f.read.scan(/<img alt=".*?" src="(.*?)"/m).uniq
end
会自动对url不同进行处理
Fibers, Threads,and Processes
Fiber 在ruby1.9中新增纤程
Fiber 用于将元素保存在一个临时的Fiber中,然后进行返回
words = Fiber.new {
Fiber.yield word.downcase
}
读取的时候.使用resume方法 返回源对象
读取的时候使用类似迭代的对象进行读取操作
更完整的解释应该是,将对象放入指定小线程中执行,使用resume得到结果 (异步)
创建多线程的方式
Thread.new(args){block} 的方式创建新的线程 ,返回线程对象
可以使用该对象的join进入该线程,也可以是执行该线程
sleep(rand(0.1)) 用于在线程体中进行休眠, rand用于生成0-1之间的小数
Thread.abort_on_exception = true 用于在执行线程时,忽略异常处理
Ruby中同步的方式
mutex.lock #### 锁定线程
sum = inc(sum) # one at a time, please
mutex.unlock ####
也可以使用block的方式,自动解锁
mutex.synchronize do ####
sum = inc(sum) # one at a time, please
end ####
Mutex.new本身也是对象,需要新建后使用,还提供了sleep等方法
Unit Testing
简单的创建一个单元测试类
require 'test/unit'
class TestRoman < MiniTest::Unit::TestCase
def test_simple
assert_equal("i", Roman.new(1).to_s)
assert_equal("ix", Roman.new(9).to_s)
end
end
也可以继承Test模块
class TestRoman < Test::Unit::TestCase
注意命名规则
Test作为类名开头
test_作为方法开头
可以使用 require 'dbi 进行包含数据库连接的测试
对于Class中定义的SRT=xx 这样的变量, 可以在外部使用Class::SRT进行访问, 类似Java中的静态变量
:: 也可以用于访问Module中的Class类型,然后进行实例化使用
设置源代码 编码
# coding: utf8 或# encoding: ascii
对字符进行编码转换
str= ole_str_utf.encode("iso88591")
在打开文件时,也可以通过附带参数,使用指定编码访问文件
f = File.open("iso88591.txt", "r:iso88591")
也可以组合使用读取,和输出使用不同的编码
f = File.open("iso88591.txt", "r:iso88591:utf8")
the first is the external encoding, and the second is the internal encoding.
读取二进制文件的方法
f = File.open("iso88591.txt", "rb")
使用cgi.rb 可以搭建基于CGI的网络应用
Haml and erb/eruby, 用于生成HTML的模板
如果需要生成XHTML或者xml,可以使用Builder
Haml更多的使用在内嵌的代码中生成HTML
erb,更多的使用模板文件进行生成文件,当然也可以嵌入使用
Ruby and Microsoft Windows
Ruby提供了丰富的操作Windows Api的类库
如 使用Email打开指定网页
require 'win32ole'
ie = WIN32OLE.new('InternetExplorer.Application')
ie.visible = true
ie.navigate("http://www.pragprog.com")
生成新的Excel文件
excel = WIN32OLE.new("excel.application")
Ruby中包含了一些变量,用于保存特定情况下的信息
$! 异常信息
$@ 异常抛出的堆栈信息
names = %{ant bee cat}
result = names.map(&:upcase)
这里的&:使用比较特殊,需要研究一下,现在运行出错
在Ruby的class中提供了self对象,作用与Java中的this类似
定义静态方法的方式,在定义方法名时,使用self.MethodName, 或 ClassName.MethodName进行定义
调用就可以直接使用ClassName.methodname进行直接调用
其他的方式访问单例对象 ,定义类时
classname="" // 必须定义一个字符串 ,这样在类中使用self时,就会变成这里的赋值
class << className ,这样内部的方法就可以直接使用class调用
<<定义类的方式应用比较多一些,也可以作为变量返回.也可以用于暴露出特定的变量提供使用Class进行修改(乱)
class Test
@var = 99
class << self
attr_accessor :var
end
end
这样就可以通过Test.var对实例变量进行修改
在Ruby中可以通过在子类中,修改父类的方法访问级别,将private的方法变成public的方法
其实就是通过重载方法,然后在子类中调用super //这里也比Java简单了,直接在方法体中调用super,就可以执行父类中的同名方法
对模块的继承 extend
module Humor
def tickle
"#{self} says hee, hee!"
end
end
obj = "Grouchy"
obj.extend Humor
puts obj.tickle
也可以在类中使用
class Grouchy
extend Humor
end
puts Grouchy.tickle
include主要用来将一个模块插入(mix)到一个类或者其它模块。
extend 用来在一个对象(object,或者说是instance)中引入一个模块,这个类从而也具备了这个模块的方法。
使用的三种情况
在类中include模块,使模块中的方法成为类的实例方法
在类定义中extend模块,使模块中的方法成为类的类方法
实例方法和类方法的区别,就如同非静态方法,与静态方法的区别
Struct, 类似c中的struct, 可以用于便捷的创建class级别对象,
Person = Struct.new(:name, :address, :likes) //参数中的应该是实例变量,也可以作为构造函数动态传入
dave = Person.new('Dave', 'TX')
dave.likes = "Programming Languages"
puts dave
重写该类中的方法
Person = Struct.new(:name, :address, :likes)
class Person
def to_s
"#{self.name} lives in #{self.address} and likes #{self.likes}"
end
end
也可以写成另外中形式,更利于阅读一些
class Person < Struct.new(:name, :address, :likes)
def to_s
"#{self.name} lives in #{self.address} and likes #{self.likes}"
end
end
动态的创建类的另外一种方式,可以使用block对类的方法进行定义
some_class = Class.new do
def self.class_method
puts "In class method"
end
def instance_method
puts "In instance method"
end
end
some_class.class_method
obj = some_class.new
obj.instance_method
instance_eval and class_eval 也可以用动态创建类
"cat".instance_eval do //使用block的方式
puts "Upper case = #{upcase}"
puts "Length is #{self.length}"
end
也可以使用参数传递的方式
"cat".instance_eval('puts "Upper=#{upcase}, length=#{self.length}"')
class_evel的使用,为已存在的类添加实例方法
class MyClass
end
MyClass.class_eval do
def instance_method
puts "In an instance method"
end
end
而对已存在的class调用instance_eval,而是添加类方法,也是使用block进行传递
可以在Ruby的class类中,实现一些Hook方法,用于在类调用时,发生的一些事件进行回调,如果方法未定义,参数错误等
相关推荐
上课时作的笔记,很杂、不全,大家都可以看看,有错误的地方可以指出、修补,班上的同学也可以互相看看,看看有什么没有写、不会、不全,都可以帮忙修改,补齐。
Java 类和对象、构造函数、继承、接口、枚举、异常处理等基础知识点总结 Java 中的类和对象是面向对象编程的基础概念。类是对象的蓝图,定义了对象的属性和行为,而对象是类的实例。Java 中的类可以包含变量和方法...
NoteBook一本乱七八糟的笔记By
leetcode 2 blog-gen 本想记录一些,用hugo生成,特开此repo。怎料懒癌又犯,就直接markdown吧 XMR 41e143PwENwR3vbHrzLjVDPLVVed2ktn9KevUAjQ7XYicduskYTpAj4XYKVfJ4NYwd8XsD8CFQVXEbuDWgc9rmMHQepCWjm
这篇文档是关于中班数学活动的教学方案,名为“乱七八糟的魔女之城”,旨在通过一个有趣的故事背景,帮助幼儿理解和应用排列规律。活动的主要目标是让孩子们能够识别和运用AAB、ABB、ABC的排列模式,同时提升他们的...
相关内容的集合,适合中高级人群,挺有意思的
java的乘法口诀乱七八糟的东西,你可以看看是什么乱七八糟的东西,你可以看看乱七八糟的东西,你可以看看是什么乱七八糟的东西,你可以看看乱七八糟的东西,你可以看看是什么乱七八糟的东西,你可以看看乱七八糟的东西,你...
### 中班数学活动—乱七八糟的魔女之城教案解析 #### 活动背景与目标 本教案针对中班(通常指4-5岁年龄段)儿童设计,旨在通过一个富有创意的故事背景“乱七八糟的魔女之城”,引导孩子们在轻松愉快的氛围中探索并...
有的时候,我们按下键盘,会出现好多乱七八糟的字母或数字。那可能是其中有一个键被按下去了,没弹上来的原因。我们也可以尝试通过重新启动电脑的办法来排除键盘失灵原因是否是软件或者系统问题,如果重新启动后键盘...
阿菜的学习笔记 这绝对是一份好看的而且用心的学习笔记了 数据库 高级MySQL笔记 极客时间-MySQL45讲整理 Python基础 初步基础 初识GraphQL 数据结构 leetcode(microsoft_question) 操作系统 计算机网络 Docker基础...
200的通讯的文件,西门子200的通讯文件
乱七八糟的主题JavaDev.jar
乱七八糟.doc
标题中的“一键自动清理系统垃圾”指的是一个便捷的系统优化工具,它设计的目的是为了帮助用户快速清除计算机中无用的、占用空间的垃圾文件。这些垃圾文件通常来源于日常使用中软件的临时文件、日志文件、缓存、未...
而描述中的"一个乱七八糟的放notebook的地方"则可能意味着这个压缩包包含了各种不同主题和用途的Mathematica笔记本(.nb文件),这些笔记本可能是用户在学习或工作中创建的示例、练习或者项目。 Mathematica的核心...
【标题】:“乱七八糟”成语的起源与历史典故 【描述】:本文将深入探讨成语“乱七八糟”的来源,它源自中国古代的两个重要历史事件——“七国之乱”和“八王之乱”。 【标签】:历史、文化、成语、教育 【正文】...
《初中语文论文趣谈成语“乱七八糟”》 成语“乱七八糟”是我们日常生活中常用的表达,用来形容事物混乱无序的状态。然而,这个词背后却蕴含着丰富的历史典故,涉及中国古代两个重要的政治动荡——“七国之乱”与...
这份名为"Android一些乱七八糟的文档"的压缩包中,很可能包含了这些关键知识点的详细资料,帮助开发者深入理解Android系统的工作原理和开发技巧。 首先,关于Android布局,它是构建用户界面的基础。Android支持多种...
"java 乱七八糟的程序集合"这个标题可能指的是一个包含多种Java编程示例、练习或项目的压缩包,其中的内容可能涵盖了很多Java学习和开发的不同阶段。下面将深入探讨Java的一些关键知识点,这些知识可能在压缩包中的...
标题中的“防止桌面锁定小程序国外绿色无乱七八糟”指的是一个小型的应用程序,设计用于防止计算机进入屏保或自动锁定状态。这个程序可能是为了解决用户在进行长时间工作或者游戏时,因系统自动锁定或激活屏保而中断...