`
friendsys
  • 浏览: 347913 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

乱七八糟的Ruby笔记

    博客分类:
  • Ruby
阅读更多
全当为了体会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方法,用于在类调用时,发生的一些事件进行回调,如果方法未定义,参数错误等












分享到:
评论
1 楼 lBovinl 2014-12-17  
完全是一头雾水~o(︶︿︶)o 唉

相关推荐

Global site tag (gtag.js) - Google Analytics