Ruby 札記 - 縱覽優雅的 Ruby

GracKanil發表於2018-07-27

“Ruby is simple in appearance, but is very complex inside, just like our human body.” — Matz, creator of the Ruby programming language

前言

先縱覽一下整體 Ruby 的語法,粗略的讀一下線上教程 《ruby基礎教程(中文第四版)》,如果連線失效,可以到 連結: https://pan.baidu.com/s/1TUeRBYz0e7RqmauTftqXhA 密碼: 2qpk 下載 epub(注:為了分享學習使用,若侵即刪)

互動式 ruby 介面

# > ruby -E UTF-8 指令碼檔名 ← 指令碼執行
# > irb -E UTF-8 ← irb 啟動
# > irb --simple-prompt 簡化輸出
複製程式碼

列印

print("Hello, Ruby.\n")      #=>Hello, Ruby.
print('Hello, \nRuby\n!\n')  #=>Hello, \nRuby\n!\n
print("Hello, \nRuby\n!\n")  #=>Hello, #換行# Ruby
puts "Hello, ", "Ruby"       #=>Hello, #換行# Ruby
puts "100"  #=> 100
puts 100    #=> 100
p "100"     #=> "100"
p 100       #=> 100
puts "Hello, \n\tRuby." #=> 轉義
p "Hello, \n\tRuby." #=> 不轉義
print "表面積=", (20 * 2), "\n"
print "表面積=#{20 * 2}\n"
複製程式碼

註釋

# 這是一個單行註釋。

=begin
我是多行註釋
哦
=end
複製程式碼

變數

定義一個變數,儲存 1

one = 1
複製程式碼

除了定義 integer ,還可以定義 String,boolean,symbol,float 等等

t_val = true
f_val = false

name = "Grac Kanil"

symbol = :symbol

price = 11.25
複製程式碼
# 區域性變數以英文字母或者 _ 開頭。
# 全域性變數以 $ 開頭。
# 例項變數以 @ 開頭。
# 類變數以 @@ 開頭
複製程式碼

常量

# 常量
> irb --simple-prompt
>> TEST = 1
=> 1
>> TEST = 2
(irb):4: warning: already initialized constant TEST
(irb):3: warning: previous definition of TEST was here
=> 2
複製程式碼

賦值

a, b, c = 1, 2, 3

a, b, c, d = 1, 2
p [a, b, c]    #=> [1, 2, nil]

a, b, *c = 1, 2, 3, 4, 5
p [a, b, c]    #=> [1, 2, [3, 4, 5]]
a, * b, c = 1, 2, 3, 4, 5
p [a, b, c]    #-> [1, [2, 3, 4], 5]

a, b = 0, 1
a, b = b, a    # 置換變數a、b 的值
p [a, b]       #=> [1, 0

ary = [1, 2]
a, b = ary
p a        #=> 1
p b        #=> 2

ary = [1, [2, 3], 4]
a, b, c = ary
p a    #=> 1
p b    #=> [2, 3]
p c    #=> 4

ary = [1, [2, 3], 4]
a, (b1, b2), c = ary    # 對與陣列結構相對應的變數賦值
p a    #=> 1
p b1   #=> 2
p b2   #=> 3
p c    #=> 4
複製程式碼

控制流

# Ruby 會認為 false 與 nil 代表假,除此以外的所有值都代表真
# then 可以省略
x = 2
if x == 2 then
    p "x=2"
end

if true
  puts "Hello Ruby."
end

if 2 > 1
  puts "bigger"
end

if 1 > 2
  puts "bigger"
else
  puts "smaller"
end

if 1 > 2
  puts "bigger"
elsif 2 > 1
  puts "smaller"
else
  puts "equal"
end

if 條件 then
 處理
end

if 條件 1 then
 處理 1
elsif 條件 2 then
 處理 2
elsif 條件 3 then
 處理 3
else
 處理 4
end

unless 條件 then
 處理
end

unless 條件
 處理 1
else
 處理 2
end

if 條件
 處理 2
else
 處理 1
end

case 比較物件
when 值 1 then
 處理 1
when 值 2 then
 處理 2
when 值 3 then
 處理 3
else
 處理 4
end

def function?
  true
end
# 方法名為 function?,問號表示返回 boolean 型別
puts "let’s go" if function?
複製程式碼

迴圈和迭代

Ruby 中的迭代有許多種不同的形式,簡單說一下 whileforeach

迴圈次數.times do
 希望迴圈的處理
end

迴圈次數.times {
 希望迴圈的處理
}

for 變數 in 開始時的數值..結束時的數值 do
 希望迴圈的處理
end

for 變數 in 物件 do
 希望迴圈的處理
end

while 條件 do
 希望迴圈的處理
end

until 條件 do
 希望迴圈的處理
end

物件.each do | 變數 |
 希望迴圈的處理
end

物件.each {| 變數 |
 希望迴圈的處理
}

# do 也可以省略
i = 1
while i < 10 do
    p "#{i}"
    i = i + 1
end

n = 1
while n <= 10
  puts n
  n += 1
end

for n in 1....10
  puts n
end

[1,2,3,4,5,6].each do |x| 
  puts x
end
複製程式碼

each 和 loop 又有些區別,each 迭代器僅僅保持變數在 block 中,而 loop 允許變數在 block 外,如

irb --simple-prompt 中測試
?> for num in 1...5
>>   puts num
>> end
1
2
3
4
=> 1...5
>> puts num
4
=> nil

然而
>> [1,2,3,4,5].each do |n|
?>   puts n
>> end
1
2
3
4
5
=> [1, 2, 3, 4, 5]
>> puts n
NameError: undefined local variable or method `n' for main:Object
	from (irb):17
	from /Users/gekang/.rvm/rubies/ruby-2.2.4/bin/irb:11:in `<main>'
>>
複製程式碼

另外也有無限迴圈的寫法

loop do
    print "Ruby"
end
複製程式碼

集合

  • array,眾所周知,使用 index 可以操作 array,在 Ruby 中還有一些其他不同的操作方式,如push<<
?> array = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]

?> array = []
=> []
>> array.push("grac")
=> ["grac"]
>> array.push("kanil")
=> ["grac", "kanil"]
>>
?>
?> print array[0]
grac=> nil
>>

?> array = []
=> []
>> array << "Grac"
=> ["Grac"]
>> array << "Kanil"
=> ["Grac", "Kanil"]

也可以使用點語法,酷不酷?
?> array.<<("Ruby is cool,huh?")
=> ["Grac", "Kanil", "Ruby is cool,huh?"]
複製程式碼
  • hash,key-value 集合
?> hash = {
?> "key1" => "value1",
?> "key2" => "value2"
>> }
=> {"key1"=>"value1", "key2"=>"value2"}

可以使用任意型別作為 value
>> hash = {
?>   "name" => "grackanil",
?>   "age" => 20
>> }
=> {"name"=>"grackanil", "age"=>20}

hash["gender"] = "male"
複製程式碼
  • 迭代器在集合中的使用
?> array.each do |name|
?>   puts name
>> end
grac
kanil
=> ["grac", "kanil"]

?> hash.each do |property, value|
?>   puts "#{property}: #{value}"
>> end
name: grackanil
age: 20
gender: male
=> {"name"=>"grackanil", "age"=>20, "gender"=>"male"}
複製程式碼

類和物件

面嚮物件語言,自然少不了物件的概念

class Animal
  def initialize(species,habit)
    @species = species
    @habit = habit
  end
end
cat = Animal.new("feline","meow")
複製程式碼
  • attr_reader(自動生成getter)
  • attr_writer(自動生成setter)
  • attr_accessor(自動生成 getter 和 setter)

提出 getter 和 setter 的概念,主要是體現一個封裝的設計原則。

繼承

class Cat < Animal
end
複製程式碼

模組(一個工具箱)

包含一些常量和方法的集合

?> module Hi
>>   def hello_world
>>     puts "Hello, world."
>>   end
>> end
=> :hello_world

?> class Test
>>   include Hi
>>   def initialize(user)
>>     @user = user
>>   end
>> end
=> :initialize
>> test = Test.new("grackanil")
=> #<Test:0x007fa01d801af0 @user="grackanil">
>> test.hello_world
Hello, world.
=> nil

module Tools
    def class_name
        p self
    end
    # module_function :class_name
end

複製程式碼
class Son
    include Tools
end

son = Son.new
if Son.include?(Tools)
    son.class_name
end

p Son.ancestors
p Son.superclass
複製程式碼

後語

可以說及其粗略地過了下 Ruby,但快樂之意,不會因為少而泛削減絲毫,大抵這就是魅力吧 :)

路漫漫其修遠兮,吾將上下而求索。