1.Symbol類
2.sort方法
3.reduce方法
4.ARGV和gets方法的區別
5.defined?用法
6.&:first用法
7.四種相等
8.unless用法
9.super用法
10.“!”
11.刪除方法
12.“::”
13.IO實例
14.異常處理
15.require方法
16.respond_to?和respond_to_missing?
17.define_method
18.public方法的調用
19.send方法調用
20.模塊和類的區別
21.計算行數中的閉包問題
22.表達式的求值順序
23.case用法
24.map和each的返回值
25.賦值和拷貝
1.Symbol類
1.兩種形式:一種是直接冒號加名字,一種是冒號加字符串
2.在一文本中,同一Symbol對象表示的類名,方法名,變量指向同一個Symbol對象
3.對于可變的使用String,不可變的使用Symbol
1.兩種形式:一種是直接冒號加名字,一種是冒號加字符串
#下面兩種就是Symbol對象的兩種表現形式
:test
:"test"
#上面的兩種形式表示的是同一個對象,就是具有相同的object_id,指向同一個內存地址。
:test.object_id #=>355868
:"test".object_id #=>355868
#即是名字相同,symbol相同,:test和:“test”是形同的名字,所以他們是相同的symbol。
#但是如果是:@test和:test是不同的名字,所以他們是不同的symbol。
:@test.object_id # 1148868
:test.object_id # 355868
#區別于兩個值相同的字符串,他們只是值相同,但不是同一個字符串對象,沒有指向同一個內存地址
“test”.object_id #=> 70114101202320
"test".object_id #=> 70114107991560
2.在一文本中,同一Symbol對象表示的類名,方法名,變量指向同一個Symbol對象
module One
class Fred
end
$f1 = :Fred
end
module Two
Fred = 1
$f2 = :Fred
end
def Fred()
end
$f3 = :Fred
$f1.object_id #=> 2514190
$f2.object_id #=> 2514190
$f3.object_id #=> 2514190
3.對于可變的使用String,不可變的使用Symbol
String有"[]="方法,Symbol沒有這個方法,因為它是不可變的。
使用Symbol方法可以降低內存,因為相同名字的Symbol指向的是同一個對象。
2.sort方法
a = [1,2,3]
a.sort #=>[1,2,3]
a.sort{|x,y|x<=>y} #=>[1,2,3]
a.sort{|x,y|y<=>x} #=>[3,2,1]
#前值和后值做比較(就是x<=>y的形式),如果前者比后者小,則按照[x,y]進行排序,就是所謂升序排列。
#如果是后值和前值做比較(就是y<=>x的形式),就是所謂的降序排列。
3.reduce方法
作用:遍歷數組中的每個值進行累加,累加值即是最后的結果。
#只添加symbol
(5..10).reduce(:+) #=>45 遍歷每個數進行累加,返回最終的累計值
#添加初始值和symbol
(5..10).reduce(1,:+) #=>46 1是初始值
#添加block,在沒有初始值的情況下,數組的第一個值初始值,即sum=5,從第二個值開始累加
#從第二個值進行累加,這是自己的理解
(5..10).inject { |sum, n| sum + n } #=>45
#添加block和初始值,從初始值開始累加
(5..10).inject(1) { |sum, n| sum + n } #=>46
4.ARGV和gets方法的區別
1.ARGV的用法:
#demo.rb:
puts "首個參數:#{ARGV[0]}"
#在終端執行代碼
demo.rb demo
#結果返回
首個參數:demo
2.gets的用法:
#demo.rb:
puts "首個參數:#{gets()}"
#執行
demo.rb demo #無效
#執行
demo.rb #回車
demo # 首個參數:demo
總結:ARGV和gets這兩個方法主要的區別是“回車”
5.defined?用法
defined?和super一樣,都是關鍵詞,不是方法
1.defined? 是一個特殊的運算符,以方法調用的形式來判斷傳遞的表達式是否已定義。
2.它返回表達式的描述字符串,如果表達式未定義則返回 nil。
#用法一:判斷變量是否定義
foo = 42
defined? foo # => "local-variable"
defined? $_ # => "global-variable"
defined? bar # => nil(未定義)
#用法二:判斷方法是否定義
defined? puts # => "method"
defined? puts(bar) # => nil(在這里 bar 未定義)
defined? unpack # => nil(在這里未定義)
#用法三:判斷yield是否可用
若 yield 調用可用,則返回真,具體返回值為字符串 "yield"
class Base
def foo
puts defined? yield
end
end
a = Base.new
a.foo # =>nil
a.foo{ this is the block} # => yield
#用法四:判斷super是否可用
defined? super,若 super 可被調用,則返回真,具體返回值為字符串 "super"
class Base
def foo
end
end
class Derived < Base
def foo
puts defined? super
end
def fun
puts defined? super
end
end
obj = Derived.new
obj.foo #=> super
obj.fun #=> nil
6.&:first用法
array = [["a",5], ["b", 3], ["a",6]]
array.uniq(&:first).sort_by(&:last)
#上面的代碼等同于
array.uniq{|a|.a.first}.sort_by{|x|x.last}
#就是按照數據的第一個元素去重,然后按照數組的第二個元素排序
7.四種相等
1."=="表示值形同
2."===",一般在case中,表示某種匹配
3."equal?"是指兩個對象的object_id值一樣,即是引用同一個對象。
4."eql?"要求值和對象類型都必須相同。
1. "=="表示值形同
#字符串的內容相同
a = "string"
b = "string" + ""
a == b #=>true
#數值相同
a = 1
b = 1.0
a == b #=>true
2. "===",一般在case中,表示某種匹配
case some_object
when /a regex/
# The regex matches
when 2..4
# some_object is in the range 2..4
when lambda {|x| some_crazy_custom_predicate }
# the lambda returned trueend
#上面的代碼和下面代碼的實現形式:
if /a regex/ === some_object
# The regex matches
elsif (2..4) === some_object
# some_object is in the range 2..4
elsif lambda {|x| some_crazy_custom_predicate } === some_object
# the lambda returned trueend
3. "equal?"是指兩個對象的object_id值一樣,即是引用同一個對象。
obj = "a"
other = obj.dup
obj == other #=> true
obj.equal? other #=> false
obj.equal? obj #=> true
a = "string"
b = "string" + ""
a.object_id #=>70268974328100
b.object_id #=>70268970910720
a == b #=>true #a和b的數值相同
a.equal?b #=>false #a和b有不同的object_id
a = 1
b = 1.0
a == b #=>true #=>a和b的數值相同
a.object_id #=>3
b.object_id #=>-36028797018963966
a.equal?b #=>false #a和b具有不同的object_id
4. "eql?"要求值和對象類型都必須相同
a = "string"
b = "string"+""
a.eql?b #=>true
#上面的a和b兩個值相同,并且屬于String類
a = 1
b = 1.0
a.eql?b #=>false
#上面的a和b兩個值相同,但是1屬于Integer類,b屬于Float類
8.unless用法
unless相當于if not ,如果unless后面的語句執行的結果為false,則該語句執行,如果為true,則該語句不執行。
#代碼如下所示,當unless后面為false的時:
def demo
puts "test" unless false
end
demo #=>這個執行結果為test
#當unless后面為true時:
def demo
puts "test" unless true
end
demo #=>這個執行結果為nil
9.super用法
super是調用父類方法的執行,但是super和super()的調用結果不同。
1.super()表示不帶參數,不把參數帶入到父類中。
2.super表示需要將參數帶入到父類中,并且執行相應的方法。
3.使用super時,從繼承體系中的上一層尋找和當前同名的方法,同樣適用于module
4.報錯之后,super之后的代碼不執行
5.使用super時引發method_missing方法
1.第一種:使用super()方法:
class Foo
def show
puts "Foo#show"
end
end
class Bar < Foo
def show(text)
super()
puts text
end
end
Bar.new.show("test")
#下面是結果
Foo#show
test
#使用super()方法,不將參數帶入到父類的show方法中,父類的show方法也不存在調用參數。
2.第二種:使用super方法:
class Foo
def show
puts "Foo#show"
end
end
class Bar < Foo
def show(text)
super
puts text
end
end
Bar.new.show("test")
#wrong number of arguments (given 1, expected 0) (ArgumentError)
上面的代碼中super方法會將text這個參數傳遞給父類的show方法,但是父類的方法其實沒有參數選項,因此出錯。
#代碼修正
def show(text)
puts "#{text}, Foo#show"
end
3.同樣適用于module
module One
def demo
puts "this is the method one demo"
end
end
module Two
include One
def demo
super
puts "this is the method two demo"
end
end
class A
include Two
end
obj = A.new
obj.demo
#結果
this is the method one demo
this is the method two demo
4.使用super報錯之后不會執行super之后的語句
class Demo
def method_missing(name, *args, &block)
super
puts "this is the method_missing"
end
end
obj = Demo.new
obj.cc #undefied method cc
#并且super之后的代碼不執行
5.使用super時引發method_missing方法
class Father
def laugh
super
end
end
Father.new.laugh #=>no superclass method `laugh' NoMethodError
#如果在繼承體系中定義了method_missing方法,將丟失默認的提示信息
class Father
def laugh
super
end
def method_missing(method)
puts "this is the missing method"
end
end
Father.new.laugh #=> this is the missing method
10.“!”
compact
#返回了去除了nil的對自身拷貝的數組,但是自身數組其實沒有變化
Returns a copy of self with all nil elements removed.
a = ["a","b",nil].compact
a.compact #=>["a", "b"]
a #=>["a","b",nil]
compact!
#改變了原來的數組
Removes nil elements from the array.
Returns nil if no changes were made, otherwise returns the array.
#如果存在nil,則返回去除了nil的數組
a = ["a","b",nil]
a.compact! #=>["a","b"]
a #=>["a","b"]
#如果不存在nil,則返回nil
a= ["a", "b"].compact! #=>["a", "b"]
a #=>["a","b"]
11.刪除方法
兩個刪除方法,包括undef_method和remove_method方法
1.前者方法會刪除所有包括繼承來的方法,而后者只刪除接受這自己的方法,保留繼承的方法
2.這兩個方法都是Module類的實例方法,可以在類中直接使用。
class Parent
def demo
puts "this is the parent"
end
end
class Child
def demo
puts "this is the child"
end
end
obj = Child.new
obj.demo #=> "this is the child"
#使用remove_method方法
class Child
remove_method :demo
end
obj =Child.new
#說明刪除了自己的方法,保留了繼承的方法
obj.demo #=>"this is the parent"
#使用undef_method方法
class Child
undef_method :demo
end
obj =Child.new
#說明刪除了所有的方法,包括繼承來的方法
obj.demo #=>undefined method demo
12."::"
示例:
module Foo
class Bar
A = “demo one”
end
B = "demo two"
class Tao
delf self.method2
"method2"
end
end
class Zen
def method2
"method2"
end
end
class ::FooBar
def self.method1
"method1"
end
end
end
puts Foo::Bar::A #調用類名
puts Foo::B #調用常量
puts Foo::Tao::method1 #調用類方法
puts Foo::Zen::new::method2 #調用實例方法
FooBar::method1 #::表示 root namespace
#第一種情況:雙引號是定義namespace或者叫做scope用的,當使用Foo::Bar的時候,實際上是在找名字叫做Foo的namespace,然后返回里面的Bar參數
這個Bar可以是個常量,可以是個類,可以是個方法(類名和方法名在Ruby中被視為常量)
#第二種情況:“::”還能用來找真正的常量
class Foo
Bar = "hello" #常量
bar = "hello" #局部變量
end
Foo::Bar #=>"hello"
Foo::bar #=>出錯
Foo.Bar #=>出錯
Foo.Bar #=>出錯
#第三種情況:“::”在開始的位置則表示回到root namespace,不管前面套了幾個module,而這個root namespace是Object
puts self #=>main
puts self.class #=> Object
#第四情況:一般情況下是module做為namespace,但是其實class其實也可以作為namespace:
class Externel
#class Internel換成module Internel效果也是一樣的
class Internel
def self.class_method
puts "this is the class method"
end
def instance_method
puts "this is the instance method "
end
end
end
Externel::Internel.class_method #=>"this is the class method"
Externel::Internel::new::instance_method #=> "this is the instance method"
13.IO實例
#####實例:寫Blog
class Blog
attr_accessor :author, :title, :time, :content
def initialize(author = "blackanger", title, content)
@author = author
@title = title
@content = "#{content}"
@time = Time.now.strftime("%Y-%m-%d %H:%M:%S")
end
def write
File.open("blog_date", 'a+') do |f|
enter(f)
f.write DATA.read
enter(f)
f.write @time
enter(f, 2)
f.write "Title: #{@title}"
enter(f, 2)
f.write "Content:"
enter(f)
f.write @content
enter(f)
end
end
def self.read
File.open("blog_date", "r") do |f|
f.each_line{|el| puts el}
end
end
def enter(f, n=1)
n.times{f.write "\n"}
end
end
if ARGV[0] == "read"
Blog.read
else
puts "opening the blog data file .."
puts "請輸入標題:"
title = STDIN.gets.chomp
puts "請輸入內容:(輸入END結束內容)"
content = ""
STDIN.each_line do |str|
content << str
break if str.chomp == "END"
end
puts "OK,正在寫入文件.."
blog = Blog.new(title, content)
blog.write
puts "提交成功! 下面是您的Blog!"
puts "當前目錄:#{__dir__}, 當前文件:#{__FILE__}"
Blog.read
end
__END__
#------
#copyright
#------
14.異常處理
#代碼示例
begin
1/m
raise "error A"
#fail "Error"
rescue =>e
puts "#{e.message}"
raise "error B"
m +=1
retry
else
puts "test"
ensure
puts "must to do"
end
1. begin .. end 語句可以放在方法里面,也可以放在類里面
#如果放在方法里面可以省略保留字begin,end,直接書寫rescue和ensure:
def foo
rescue =>ex
異常處理
ensure
后處理
end
#如果放在類里面,也可以直接使用rescue和ensure,省略begin和end
#但是的話如果類定義途中發生異常,那么異常發生部分后的定義方法就不會再執行,因此一般不在類定義中使用他們
2. 這里幾個關鍵詞比如begin,rescue,ensure,retry,raise,fail,else等,其中begin,rescue,ensure,retry,else是保留字,而fail和raise是Kernel的module method,其兩者的功能都是一樣的,都是拋出相應的內容。
3. ensure的作用是無論上面的代碼是否執行,ensure里面的代碼都會執行。
4. rescue只接受異常類,而符號=>與hash中的符號的表示意義不一樣,這里表示的意思是傳遞。
5. retry是重新執行這段代碼的意思,而這里被重新執行的代碼是begin到rescue這段代碼,使用retry容易產生死循環。
6. else表示沒有rescue的時候進行執行else里面的代碼。
7. rescue中的代碼如下所示,它一般捕獲的異常類。
rescue =>e
#一般是這種形式,如果沒有指明是哪個異常類的話,默認是使用StandardError類
#如果按照rescue =>e 這種形式來寫的話,如果實際報出的錯誤不是StandardError類的對象的話,則這個錯誤捕獲不到。
rescue ZeroDivisionError =>e #也可以表示成這種形式
具體代碼如下:
def divide(m)
begin
1/m
rescue ZeroDivisionError => e
m += 1
retry
end
end
divide 0 #=>1
#接上上面的代碼繼續進行說明,如果 =>e前面沒有指明類,默認是StandardError類的對象,但是如果捕獲LoadError異常的話,代碼報錯:
def divide(m)
begin
require "xxx"
1/m
rescue =>e
puts "#{e.class}"
end
end
#執行上面的代碼會報錯,但是執行下面的代碼會出現預期的結果
def divide(m)
begin
require "xxx"
1/m
rescue LoadError =>e
puts "#{e.class}"
end
end
8.rescue可以捕獲多個異常,見如下的代碼所示:
def divide(m)
begin
require "xxx"
1/m
rescue LoadError => e
puts "#{e.class}"
rescue ZeroDivisionError => e
puts "#{e.class}"
end
end
divide(0) # LoadError
9. rescue的另外一種用法
def divide(m)
1/m rescue $!
end
divide(0) # ZeroDivisionError: divided by 0
10. ensure不會影響begin的返回值:
def divide(m)
begin
1/m
rescue ZeroDivisionError => e
puts "#{e.message}"
m += 1
retry
ensure
puts m*2
end
end
a = divide 0
puts a # =>1,返回值即是begin中的返回值
11. 在ensure中添加return關鍵詞,則影響方法的返回值:
def divide(m)
begin
1/m
rescue ZeroDivisionError => e
puts "#{e.message}"
m += 1
retry
ensure
return m*2
end
end
a = divide 0
puts a # =>2,方法的返回值變為return的值
begin
1/m
rescue =>e
puts "#{e.message}"
m += 1
retry
else
puts "something"
ensure
puts "must to do"
end
#如果方法調用的過程中m取值為0,則會報出異常,報出異常的方式其實和raise方法一致:
raise "error A" if m == 0
代碼的具體執行步驟如下:
1.create Exception Object
2.set traceback
3.set global exception variable $!
15.require方法
#require方法
如果require的文件不是絕對路徑,那么從$LOAD_PATH($:)中尋找相應的文件
可以在終端中執行$LOAD_PATH,查看其中的內容
#relative_require方法
如果要應用相同目錄下的文件內容,需要使用relative_require方法
16.respond_to?和respond_to_missing?
#method_missing不友好,它能夠代理方法,但是respond_to?的過程中,結果是false:
class Demo
def method_missing(method, *args, &block)
if method.to_s =~ /play_(\w+)/
puts "here is #{$1}"
else
super
end
end
end
p = Demo.new
p.play_with_girl #=>here is with_girl
p.respond_to? :play_with_girl #=> false
#為了讓respond_to?返回true,可以使用下面的語句:
class Demo
def method_missing(method, *args, &block)
if method.to_s =~ /play_(\w+)/
puts "here is #{$1}"
else
super
end
end
def respond_to?(method, *)
method.to_s =~ /play_(\w+)/ || super
end
end
p = Demo.new
p.play_with_girl #=>here is with_girl
p.respond_to? :play_with_girl #=> 0
#但是其實上面的play_with_girl還是不像一個方法,見如下代碼:
p.method :play_with_girl #=> NameError,undefined method
#為了解決上面的問題,引入respond_to_missing?方法,下面是完整的解決方案:
class Demo
def method_missing(method, *args, &block)
if method.to_s =~ /play_(\w+)/
puts "here is #{$1}"
else
super
end
end
def respond_to_missing?(method, *)
method =~ /play_(\w+)/ || super
end
end
p = Demo.new
p.play_with_girl #=> here is with_girl
p.respond_to? :play_with_girl #=> true
m = p.method(:play_with_girl)
m.call #=> here is with_girl
m.name #=> play_with_girl
Demo.send :define_method, :hello, m
p.hello #=> here is with_girl
17.define_method
#一般用法:下面的代碼直接在類中使用define_method方法定義:test的類
class Test
define_method :test do
puts "this is the define_method demo"
end
end
obj = Test.new
obj.test #=>"this is the define_method demo"
疑惑:為什么可以在類中直接使用define_method方法,以為是實現了module_funciton的功能
module_functon主要實現了下面的兩個功能:
1.模塊名.方法名直接調用
Kernel.puts "this is the test"
2.類似于關鍵字在程序的任何部分進行調用
puts "this is the test"
但是,其實在define_method不能實現上面的兩個功能
最終解釋:
1.define_method是Module類私有實例方法,同時Module類是Class類的父類。
2.define_method做為一般類對象的類方法被直接調用。
#irb: Module.private_instance_method.grep(/define_method/)
#irb: [:define_method]
class Module
def demo
puts "this is the demo"
end
private :demo
end
class Test
#對象類中的私有方法,在對象中可以被直接調用,而且必須是隱式調用
demo
end
18.public方法的調用
1.public的類方法和實例方法可以被顯示調用,也可以被隱式調用。
2.這個方法必須在所在的類或者實例化對象的作用域內。
#公開的類方法可以被顯示調用,可以被隱式調用:
class DemoClass
class << self
def demo_method
puts "this is the class method"
end
end
DemoClass.demo_method #如期執行
demo_method #如期執行
end
demo_method #會報undefined method or variable
#上面的方法不在DemoClass這個作用域中,而在Object這個類的作用域中。
#公開的實例方法可以別顯示調用,也可以被隱式調用:
class DemoClass
def demo_method
puts "this is the instance method"
end
end
obj = DemoClass.new
obj.demo_method
obj.instance_eval{ demo_method }
19.send方法調用
send是BasicObject類的public instance method,可以被調用的對象包括:
1.普通對象
2.普通類
3.普通模塊
4.Kernel模塊
class DemoClass
class << self
def class_method
puts "this is the class method"
end
end
def demo_method
puts "this is the demo"
end
end
obj = DemoClass.new
obj.demo_method
obj.send(:demo_method) #可以被普通對象調用
Kernel.send(:puts, "cc") #可以被Kernel模塊調用
DemoClass.send(:class_method) #可以被普通類調用
module Mod
class << self
def module_method
puts "this is the module method"
end
end
end
Mod.send(:module_method) #可以被普通模塊進行定義
#send方法可以被普通對象調用
DemoClass.superclass #=> Object
Object.superclass #=>BasicObject
#類DemoClass間接繼承于BasicObject類,繼承send方,DemoClass的普通對象可以調用BasicObject類的實例方法send。
#send方法可以被普通類進行調用
DemoClass.class #=>Class
Class.superclass #=>Object
#send方法是Class類的實例化方法,亦是DemoClass類的類方法。
#send方法可以被普模塊調用
Mod.class #=>Module
Module.superclass #=>Object
#send方法是Module類的實例方法,是其實例化對象即普通模塊的模塊方法。
#send方法可以被Kernel模塊調用
#Kernel模塊是Module類的一個普通實例化對象,代碼如下所示:
Kernel.class #=>Module
20.模塊和類的區別
1.在類中,類的實例方法是其類對象的類方法。
2.因為類和模塊相比,只是增加了三個方法(new, allocate,superclass)
#類的形式
class String
def self.inherited(subclass)
puts "#{self} was inherited by #{subclass}"
end
end
class MyClass < String; end #=> String was inherited by MyClass
#inherited是Class類的私有實例方法:
Class.private_instance_methods.grep(/inherited/) #=>[:inherited]
#String是Class的實例化對象,因此Class的實例方法也就成了String類(本質上是一個對象)的類方法。
#模塊的形式
module M; end
M.class #=>Module
module M
def self.incluede(othermod)
puts "M was mixed into #{othermod}"
end
class C
include M
end
end
#include方法是類Module的私有實例方法:
Module.private_instance_methods.grep(/include/) #=>[:include]
#普通的模塊其實是類module的對象,因此moudle類的實例方法是其實例化對象(也就是一個普通模塊)的模塊方法
所以,類和模塊在原理上其實是一致的。
21.計算行數中的閉包問題
閉包:是引用了一個作用域外的變量并且可以被調用的函數。
ltotal = 0
ARGV.each do |file|
begin
input = File.open(file)
l = 0
input.each_line do |line|
l += 1
#ltotal += l #最終執行結果為153
#檢測這個問題的方法是將如下的結果在控制臺打印出來
#puts l
#puts ltotal
end
input.close
ltotal += l #最終執行結果為17
rescue =>e
puts "#{e.message}"
end
end
puts ltotal
22.表達式的求值順序
1.解釋器對每個表達式都是從右向左求值的
2.同一個作用域的方法才能調用,不同作用域的方法不能調用
3.send方法接受返回字符串對象和符號對象的方法名的方法也是可以的。
1.解釋器對每個表達式都是從右向左求值的
class Computer
def mouse
component :mouse
end
def component(name)
puts "get the #{name} information in the computer"
end
end
cp = Computer.new
cp.mouse
#返回預期的結果:
def mouse
component :mouse
end
#更改代碼
def mouse
component(mouse) #出現SystemStackError錯誤
end
#解釋器對每個表達式都是從右向左求值的的
def mouse
component :mouse#將:mouse理解為符號對象
end
#更改代碼
def mouse
component(mouse) #將mouse理解為方法,因此出現如上死循環錯誤
end
#出現如下的錯誤
component(mouse)
component(component(mouse))
component(component(component(mouse)))
#改動代碼
def mouse
component cc #undefined local variable or method "cc"
end
#解釋:解釋器對表達式是從右向左求值,但是cc這個變量沒有被定義過,按照這個形式,有可能是方法,也有可能是局部變量。
2.同一個作用域的方法才能調用,不同作用域的方法不能調用
class MyClass
def my_method(my_arg)
puts my_arg*2
end
end
obj = MyClass.new
obj.send(:my_method, 3) #=>6
obj.send("my_method", 6) #=>6
obj.send(my_method, 6) #=> undefined variable or method error
#調用方法需要考慮作用域的
class Computer
def mouse
component mouse
end
def component(name)
puts "get the #{name} information in the computer"
end
end
#component方法調用mouse方法,這兩個方法在同一個作用域中
#調用my_method方法的時候,會在該方法的作用域中尋找該方法,但是my_method方法跳出MyClass之后,就失效了,該方法的作用域是頂級作用域
#區別obj.send(my_method)和obj.my_method
obj.send(my_method, 6) #=> undefined variable or method error
3.send方法接受返回字符串對象和符號對象的方法名
class MyClass
def my_method(my_arg)
puts my_arg*2
end
end
obj = MyClass.new
def simulate
:my_method
end
obj.send(simulate, 6) #=>6
23.case用法
#第一種情況類似于if語句
year=2012
leap = case
when year%400 == 0 then true
when year%100 == 0 then false
else year%4 == 0
end
puts leap
#第二種情況case語句的頂部指定一個目標,而每個when從句列出一個或者多個比較條件
input="run"
case input
when "debug"
print "debug time"
when "run"
print "run now"
else
print "wrong"
end
24.map和each的返回值
需要取出tag數組中的name值,并且作為字符串顯示,兩個方法都是進行遍歷,但是each返回的還是原來的數組,map返回的是遍歷后的數組,所有后者能達到所要的效果,兩個方法都不能改變數組本身。
#map
a=[[1,"a"], [2,"b"]]
a.each(&:first).join(",") #=>[[1,"a"], [2,"b"]]
b.each(&:first).join(",") #=>"1,2"
25.賦值和拷貝
賦值是創建一個引用,如果將一個對象賦值給另外一個對象,那么這兩個對象指向同一個引用:
str1 = 'hello' # => "hello"
str1.object_id # => 17940720
str2 = str1 # => "hello"
str2.object_id # => 17940720
兩個對象均指向同一個引用,如圖所示:
兩個對象均指向同一個引用
如果修改其中一個對象,則會改變其引用,也即是改變另外一個對象。但是還是指向的是同一個引用。
str2 << '!' # => "hello!"
str1 # => "hello!"
str2 # => "hello!"
str1.object_id #=>70296829690720
str2.object_id #=>70296829690720
如果對其中一個對象重新復制,則兩個對象不再指向同一個引用。
str2 = 'ruby!' # => "ruby!"
str2.object_id # => 17304640
str1.object_id # => 17940720
對象被重新賦值之后不再指向同一引用