ruby語(yǔ)言基礎(chǔ)
1.ruby簡(jiǎn)介
編程界幾大魔幻語(yǔ)言,c++、JavaScript、ruby和perl等,個(gè)個(gè)都是神奇而強(qiáng)大,好壞不一,魔幻的別稱不是沒(méi)來(lái)由。perl這輩子我是不會(huì)碰,c++和JavaScript算是一家,學(xué)會(huì)了一種,另外一種過(guò)渡不算困難,c++是愛(ài)好。剩下就是ruby了,號(hào)稱是要干死python,現(xiàn)在看來(lái)ruby其實(shí)已經(jīng)半死不活。
本文就是針對(duì)ruby的,現(xiàn)學(xué)現(xiàn)賣,希望能夠整理出一份比較容易入門的帖子。本文的角度是,假設(shè)已經(jīng)掌握了一門語(yǔ)言,主要目的是快速掌握ruby的關(guān)鍵語(yǔ)言特性。因?yàn)槟阄业臅r(shí)間都很寶貴,不需要在語(yǔ)言語(yǔ)法上浪費(fèi)過(guò)多的時(shí)間。
1.1.hello world
經(jīng)典的例子,就是是hello world,ruby中一行語(yǔ)句就可以完成,和python類似。
# 這是一行,注釋方法和python類似
puts 'hello world' # 括號(hào)可以省略
# p程序員專用 輸出字符串時(shí)會(huì)帶有引號(hào),類似puts
p "hello world"
=begin
這是多行注釋
puts有多個(gè)參數(shù)時(shí),每個(gè)輸出都會(huì)換行
print 只在最后添加換行
p 一般是給編程程序員使用
=end
print 'hello', 'world' # 等價(jià)于print('hello', 'world')
puts 'hello', 'world'
ruby中在<<之后,您可以指定一個(gè)字符串或標(biāo)識(shí)符來(lái)終止字符串,且當(dāng)前行之后直到終止符為止的所有行是字符串的值。
# 很ruby的用法,
print <<E # E要成對(duì)出現(xiàn),也可以是其他單詞或者字母
hello world!
hello wrold!
E
# 輸出
hello world!
hello wrold!
# 您可以把它們進(jìn)行堆疊,不過(guò)先后順序是不能亂
print <<"foo", <<"bar"
hello foo.
foo
hello bar.
bar
1.2.ruby之旅
1.2.1.順序語(yǔ)句
定義變量的語(yǔ)法。
# 定義變量,和python一樣
i = 1 # 整數(shù)
hi = 0xff # 16進(jìn)制數(shù)
bi = 0b1011 # 二進(jìn)制數(shù)
# 全局變量
$gi = 0
$gs = 'this is global string'
# 局部變量作用域,和python差不多
if true then
if_local_var = 0
end
puts if_local_var # if語(yǔ)句內(nèi)定義的變量依然可見(jiàn)
ruby語(yǔ)言是純面向?qū)ο?,連標(biāo)準(zhǔn)類型也是對(duì)象。
# 字符串
s = 'hello world' # 字符串
ss = "string value is #{i}" # 雙引號(hào)可以通過(guò)變量格式化,有點(diǎn)類似python模板
# 下面字符串定義語(yǔ)法,很ruby
s = %q{hello world} # 同 s = 'hello world'
ss = %Q{string value is #{i}} # 同 ss = "string value is #{i}"
# 多行字符串定義
ss = %Q|first line
"second line"
|
puts ss # 輸出多行 ,你可以使用{}、[]、||、<>、??、//、\\、;;等等都可以,不一定是{}
# 空值,nil不代表''
s = ''
if s == nil
puts 's is null'
end
# 浮點(diǎn)數(shù)
f = 3.14
puts f.round # 3 四舍五入
puts f.ceil # 4 進(jìn)位
puts f.to_i # 3 轉(zhuǎn)換整數(shù)
其他語(yǔ)句的語(yǔ)法舉例:
# 多重賦值
a, b, c = 1,2,3 # 定義變量a、b、c
a, b = b, a # 交換a和b的值
array = [1,3,4] # 定義數(shù)組
a, b, c = array # 數(shù)組解析到變量中
# 三元運(yùn)算符?: 語(yǔ)句,和C++語(yǔ)法保持一致
max = (10 > 5) ? 10 : 5
# 常量,全部采用大寫,如果改寫會(huì)發(fā)出告警
PI = 3.14
# 基礎(chǔ)的表達(dá)式 比如+ - * / % **
a = 1 * 2
a += 1 # 等價(jià)于a = a + 1
# 范圍運(yùn)算符
puts 1..3.to_a # [1, 2, 3]
puts 1...3.to_a # [1, 2]
# 數(shù)組與數(shù)組迭代
array = [1, 2, 3, 4]
array.each do |it|
puts it
end
puts it # 注意,it生命周期已結(jié)束,it未定義
# 數(shù)組長(zhǎng)度 length和size都是獲取數(shù)組長(zhǎng)度
nums = Array[1, 2, 3, 4,5]
puts "array size is: #{nums.length} or size: #{nums.size}"
puts "#{nums}"
# hash類型,類似json
hash = {"name" => 'ruby1', "age" => 20}
hash.each do | key, value |
puts "key: #{key}, value: #{value}"
end
hash[:name] = 'ruby2' # 訪問(wèn)name節(jié)點(diǎn),不能使用hash["name"]訪問(wèn)
1.2.2.條件語(yǔ)句
控制語(yǔ)句主要有條件、循環(huán)等,好消息ruby好像沒(méi)有goto語(yǔ)句。
# 基本的條件語(yǔ)句:if 表達(dá)式用于條件執(zhí)行。值 false 和 nil 為假,其他值都為真
i = 4
if i > 10 then
puts 'i > 10'
elsif i > 5 then
puts 'i > 5'
else
puts 'i in else'
end
# if修飾符
puts 'pass' if 1 > 0
puts 'not ouput' if 0 > 0 # 條件不成立不會(huì)輸出
# unless語(yǔ)句,與if相反,unless有存在的價(jià)值嗎?
x = 1
unless x > 2
puts "x <= 2"
else
puts "x > 2"
end
# unlese修飾符
i = 0
puts 'get unless' unless i > 0
# case,這個(gè)確實(shí)有點(diǎn)丑
age = 5
case age
when 0 .. 2
puts "baby"
when 3 .. 12
puts "child"
when 13 .. 18
puts "young"
else
puts "adult"
end
# ruby沒(méi)有with語(yǔ)句,可以自己定義一個(gè)
1.2.3.循環(huán)語(yǔ)句
循環(huán)語(yǔ)句主要有while、do、until、for、break、next、redo、retry等。
# while語(yǔ)句與while修飾符
a, b = 1, 10
while a < b do
puts "a is #{a}"
a += 1
end
a, b = 1, 10
begin
puts "a is #{a}"
a += 1
end while a < b
# until語(yǔ)句
a, b = 1, 10
until a >= b do
puts "a is #{a}"
a += 1
end
# until修飾符
a, b = 1, 10
begin
puts "a is #{a}"
a += 1
end until a >= b
# for語(yǔ)句
for i in 0..10
puts "i = #{i}"
end
puts i # i依然有定義,i = 10
#遍歷數(shù)組
names = ['a', 'b']
for name in names
p name
end
# each
(0..10).each do |ii|
puts "ii = #{ii}"
end
puts ii # 此語(yǔ)句失敗
# break
for i in 0..10
if i > 3 then break end
puts "i = #{i}"
end
# next if
for i in 0..10
next if i < 3 # 如果i < 3就繼續(xù)下次循環(huán)
puts "i = #{i}"
end
# 等價(jià)于
for i in 0..10
if i < 3 then next end
puts "i = #{i}"
end
# redo語(yǔ)句
for i in 0..10
if i < 3 then
puts "i is #{i}"
redo # 這里會(huì)出現(xiàn)死循環(huán)
end
end
# retry語(yǔ)句已經(jīng)廢棄
# do語(yǔ)句
3.times do
p 'times1'
end
# 用花括號(hào)代替 do end
3.times { p 'times2' }
3.times do |i|
p "#{i + 1}times1"
end
3.times { |i|
p "#{i + 1}times2"
}
name = ['a', 'b']
names.each do |name|
p name
end
1.2.3.異常語(yǔ)句
# 異?;居梅?begin
p ii # ii未定義
rescue NameError
# NameError是指定異常,如何不寫,就是捕獲所有異常
p 'var ii is undefine'
ensure
p 'must exec' # 無(wú)論是否有異常,一定會(huì)執(zhí)行
end
# 主動(dòng)拋出異常
raise Exception.new('this is exception')
raise RuntimeError.new('this is runtime exception')
# 異常隱藏問(wèn)題,同大多數(shù)語(yǔ)言一致
begin
p ii # ii未定義
rescue Exception => err
p "you are here #{err}" # 會(huì)執(zhí)行到這里
rescue NameError
# 實(shí)際拋出NameError,被上面捕獲攔截了,因?yàn)镹ameError是Exception的子類
p 'var ii is undefine'
end
1.2.3.函數(shù)
函數(shù)的基本定義:
# 定義一個(gè)方法
def first_method()
puts 'this is first method'
end
# 帶參數(shù)
def second_method(name, age=100)
puts "name: #{name}, #{age}"
end
second_method('china')
second_method('earth',age=1000)
second_method(age=10000, name='sun') # 這里調(diào)用結(jié)果不是我們預(yù)期的,和python是有區(qū)別的
second_method(age:10000, name:'sun') # 這樣調(diào)用也是不行的
# 括號(hào)可以省略
second_method 'china', 100
# 定義時(shí)候,也可以不用括號(hào)
def third_method name, age
puts "name: #{name}, #{age}"
end
third_method 'sun', 10000
# 返回值 return
def return_one(a)
return a * a
end
def return_two(a)
return a * a, a ** 2
end
return_one(10)
a, b = return_two(10)
# 返回return,可以省略
def return_one(a)
a * a # 這里省略了return,這很ruby
end
return_one(10)
函數(shù)的參數(shù)可變
# 可變參數(shù)函數(shù)
def sum(*element)
ret = 0
for i in 0...element.length
ret += i
end
return ret
end
sum(1,2,3,4,5)
關(guān)鍵字參數(shù),類似與python,不過(guò)python統(tǒng)一了關(guān)鍵字參數(shù)和非關(guān)鍵字參數(shù)用法。
def distance(x:0, y:0, z:0)
return x**2 + y **2 + z **2
end
puts distance(z:1, x:2, y:3)
puts distance(1,2,3) # 語(yǔ)法錯(cuò)誤
# 可變關(guān)鍵字參數(shù)
def distance(x:0, y:0, z:0, **kwags)
a1 = x**2 + y **2 + z **2
for v in kwags.values
a1 += v ** 2
end
return a1
end
puts distance(x:1,y:2,z:3,m:4,n:5)
# 關(guān)鍵字參數(shù)和非關(guān)鍵字參數(shù)可以混用
def distance(x, y, z, **kwags)
a1 = x**2 + y **2 + z **2
for v in kwags.values
a1 += v ** 2
end
return a1
end
puts distance(1,2,3,m:4,n:5)
puts distance(1,2,3,**{m:4,n:5})
函數(shù)的別名,取消函數(shù)定義、嵌套函數(shù)。
# 方法別名alias
alias mysum sum
mysum(1,2,3,4,5) # 調(diào)用新的別名方法
# 去除方法定義, 再調(diào)用sum和mysum都會(huì)出現(xiàn)方法未定義
undef mysum
# 嵌套函數(shù)
def outer_func()
def inner_func()
puts 'this is inner function'
end
inner_func()
puts 'this is outer function'
end
outer_func()
inner_func() # 這里也可以調(diào)用內(nèi)部函數(shù)
outer_func.inner_func() # 調(diào)用失敗
# 取消定義
undef outer_func
inner_func() # 這里依然可以調(diào)用
lambda函數(shù)定義
# lambda函數(shù)
ff = lambda{|a,b| return a * b}
ff.call(10,20) # 這里ff調(diào)用需要加上.call
ruby由于函數(shù)參數(shù)都是動(dòng)態(tài)類型,所以也就沒(méi)有了函數(shù)重載能力。這一點(diǎn)和python比較類似。另外,ruby語(yǔ)言層面沒(méi)有支持裝飾器。
1.2.3.類
用戶可以通過(guò)類創(chuàng)建自定義類型,關(guān)鍵字class和大多數(shù)語(yǔ)言一樣的。我們定義一個(gè)類Student,有兩個(gè)屬性name和age,代碼如下:
class Student
# attr_accessor標(biāo)示讀寫,只讀attr_reader、只寫attr_writer
attr_accessor :name
attr_accessor :age
# 構(gòu)造函數(shù) initialize,接受兩個(gè)參數(shù)
def initialize(name, age)
# 實(shí)例變量?jī)|@開頭
@name=name
@age=age
end
end
s = Student.new('ssss', 100)
puts s.name
s.name = 'ssss2'
puts s.name
s.age = 200
puts s.age
類型定義,共有,私有和保護(hù)方法
class MyClass
def private_method()
puts 'private method'
end
def protected_method()
puts 'protected method'
end
def public_method()
puts 'public method'
end
private :private_method
protected :protected_method
end
mc = MyClass.new()
mc.public_method()
# run error
mc.protected_method()
mc.private_method()
類定義靜態(tài)屬性,需要定義相應(yīng)的方法,外部才能夠訪問(wèn)。默認(rèn)情況下,靜態(tài)屬性是私有的。
class StaticClass
@@s_int = 0
@@s_str = 'hello'
def s_int
@@s_int
end
def s_str
@@s_str
end
def self.s_str
@@s_str
end
# 定義類方法
def StaticClass.static_method()
puts 'this is static method'
end
end
puts StaticClass.new.s_int
puts StaticClass.s_str
puts StaticClass.static_method()
# 靜態(tài)方法,對(duì)象不能調(diào)用
puts StaticClass.new.static_method()
類繼承
class Base
def show
puts 'show method from base'
end
def message
puts 'message from base'
end
end
class Child < Base
def message
puts 'message from child'
end
end
base = Base.new
child = Child.new
base.message()
base.show()
child.message()
child.show()
# 關(guān)于多態(tài),ruby是動(dòng)態(tài)語(yǔ)言,天生就支持類型的多態(tài)
調(diào)用父類的構(gòu)造方法
class Base1
def initialize(name, age)
puts "base init: #{name} #{age}"
end
end
class Child1 < Base1
def initialize(name, age, phone)
super(name, age)
puts "child init #{phone}"
end
end
child = Child1.new('haha', 100, '136')