Ruby 札記 - 淺嘗 Ruby 特性

GracKanil發表於2018-08-01

經過粗略的看 Ruby 相關資源,看到了很多相似或相異卻熟悉的點滴,還談不上深刻體驗,只能算記錄。仍需用心探索,決定高層建築需要夯實基礎,理解原理,體會設計。

前言

分享兩個有趣的連結

  • TryRuby:顧名思義,試試先。
  • Ruby.new:好看的皮囊千篇一律,有趣的靈魂萬里挑一。

迭代器

先不厭其煩的記錄下基礎知識,閒話少敘。談及迭代器(iteration),少不了談到相似結構——迴圈(looping)。迴圈簡要的說,是重複執行一段程式直到一個明確條件。迭代器是操作一個集合物件,如 Array 等,讓集合每一個元素執行。 看看執行一個簡單的迭代器

7.times do
  puts "Hello Iteration."
end
複製程式碼

輸入指定條件,才會停止的迴圈

input = ""
while input != "quit"
  puts "ha,#{input}"
  input = gets.chomp
end
複製程式碼

一個使用 #each 迭代器的例子

colors = ["Yellow", "Red", "Black"]
colors.each do |color| #block 開始
  puts "#{color}" #block體
end #block 結束
複製程式碼

輸出如下

?> colors = ["Yellow", "Red", "Black"]
=> ["Yellow", "Red", "Black"]
>> colors.each do |color|
?>   puts "#{color}"
>> end
Yellow
Red
Black
=> ["Yellow", "Red", "Black"]
複製程式碼

說到 iterator ,肯定和 block 強相關, 讓我們走進 block 看看一些概念。

什麼是塊(block)? 一塊在括號{}內部程式碼叫塊(block),或者do / end 之間的程式碼塊,塊(block)使 ruby 更加特殊、強大、受歡迎。

什麼是 | |? 被稱為管道,呼叫迭代器 #each 時,管道內的變數充當傳遞給塊的引數,傳遞到塊中的每個元素將等於管道內的變數名稱。為集合中的每個元素呼叫或執行塊中的程式碼一次。#each方法每次取集合中的一個元素,並將其傳遞至塊中,每個元素賦值給管道中的變數。

{ } 語法

colors = ["Yellow", "Red", "Black"]
colors.each {|color| puts "#{color}" }
複製程式碼

一切表達方法皆有值

任何表示式都有返回值,即使是nil,如下程式碼也有(有沒有覺得不可思議)

x = 10
y = 11
z = if x < y
      true
    else
      false
    end
z # => true
複製程式碼

符號不是輕量的字串

符號最好的描述是身份證。

>> :grackanil.object_id
=> 1145628
>> :grackanil.object_id
=> 1145628

?> "grackanil".object_id
=> 70162817382840
>> "grackanil".object_id
=> 70162817360420
複製程式碼

以上程式碼說明什麼?說明當符號在使用過一次後,任何相同字元的符號都會在記憶體中指向同一個物件地址,也即是 object_id 相同。字串就不同,每次都會分配新的空間,即 object_id 不同。

一切皆是物件

絲毫不誇張,整型都是物件。

?> 1.class
=> Fixnum
複製程式碼

可以改變的常量

只會有警告,但不會終止執行,但還是不建議修改。

命名約定

只是約定。

  • 區域性變數以英文字母或者 _ 開頭。
  • 全域性變數以 $ 開頭。
  • 例項變數以 @ 開頭。
  • 類變數以 @@ 開頭

關鍵值引數

從 Ruby 2.0 開始就有

def deliver(from: "A", to: nil, via: "mail")
  "Sending from #{from} to #{to} via #{via}."
end

deliver(to: "B")
# => "Sending from A to B via mail."
deliver(via: "Pony Express", from: "B", to: "A")
# => "Sending from B to A via Pony Express."
複製程式碼

真值

Ruby 把任何不是 nil 和 false 的值當作真值。和其他語言不同,可以說差異很大,其他語言,如 Python、C 等,都是會認為 0 和一些其他的值, 比如空的列表,會被當作假值。

# Ruby 中
if 0
  puts "0 為真"
else
  puts "0 為假"
end
# puts "0 為真"
複製程式碼

許可權控制宣告

許可權宣告會一直應用到類宣告底部或者直到另外一個許可權宣告開始起作用。

  • public 是公開的。
  • private 表示只有非明確指定接收者允許呼叫。私有方法呼叫只允許 self 為接收者。
  • protected 可以被類及子類的例項呼叫,同一個類的其他例項也可以呼叫。 另外,publicprivateprotected 都是方法,可以傳參,如果傳遞一個符號作為引數,那符號所代表的函式就是指定的許可權。
?> method(:public)
=> #<Method: main.public>
複製程式碼

類是開放的

可以開啟任何類,對它增加和修改。

Class Fixnum
  def month
    self * 30
  end
end
複製程式碼

1.month

以 ?和 !結尾的方法

首先,允許 ?和 ! 結尾。以問號結尾的方法表示返回布林值,以感嘆號結尾表示潛在“危險”方法,會修改self或引數。

Missing 方法

會將不存在的方法名,作為引數傳遞給 method_missingmethod_missing 預設會丟擲一個 NameError 異常。根據需要可以,可以覆蓋該方法。

def method_missing(id, *arguments)
  puts "呼叫了不存在的方法:#{id}。它的引數:#{arguments.join(", ")}"
end
1.sssss :a 2222
# 呼叫了不存在的方法:sssss。它的引數:a, 2222
複製程式碼

操作符是語法糖

大部分操作符僅僅是方法呼叫的語法糖,你可以覆蓋。

=> #<Method: main.public>
>> class Fixnum
>>   def +(other)
>>     self - other
>>   end
>> end
=> :+
>>
?> 1 + 1
=> 0
複製程式碼

當然,也有一些操作符。

=, .., ..., not, &&, and, ||, or, ::, +=, *=
複製程式碼

訊息傳遞

方法呼叫實際是訊息傳遞,不是函式呼叫。將一條訊息傳遞給另一個物件。