打造Ruby學習環境有以下三種方法
1.網路連上https://www.nitrous.io/,需註冊才可使用線上版
2.Ubuntu OS,指令為 sudo apt-get install ruby
如果是選擇此的人,需再安裝打程式碼的記事本
例如:Vim 、 Emacs 、 Sublime text... 等等
3.Mac電腦
Ruby相關社群
RubyConf Taiwan
Ruby Tuesday
Rails Girls Taipei
有裝Ruby終端機命令
gem install 包裹名 >>安裝套件
gem env >>安裝ruby細項
ruby 檔名.rb >>執行ruby程式
相關觀念
常數 大寫開頭 / 變數 小寫開頭
直接宣告變數 區域變數:存活只在方法(function)之內
$宣告變數 全域變數:存活在不同方法(function),跟類別變數類似
@@宣告變數 類別變數:存活在不同方法(function),跟全域變數類似
以下為範例
class MyClass @@value = 1 def add_one @@value= @@value + 1 end def value @@value end end instanceOne = MyClass.new instanceTwo = MyClass.new puts instanceOne.value instanceOne.add_one puts instanceOne.value puts instanceTwo.value
結果
1 2 2
@宣告變數 實體變數:存活在不同方法(function),但只能在方法(function)內設值才有傳入
以下為範例
class MyClass @one = 1 def do_something @one = 2 end def output puts @one end end instance = MyClass.new instance.output instance.do_something instance.output
結果
nil 2
實體變數參考網址:http://rpg0822.pixnet.net/blog/category/48491
程式碼參考網址:http://zh.wikibooks.org/zh-tw/Ruby_Programming/Syntax/Classes#.E5.AF.A6.E9.AB.94.E8.AE.8A.E6.95.B8.28Instance_Variable.29
只有false和nil是假的,其餘都是真的
# >>單行註解
begin end >>多行註解
|| >>OR
a||=10 >>如果a沒設定就設定10
a[:name] >>把name做標誌
private 呼叫不能有小數點
protected 呼叫能有小數點,用的方式99%跟private很像
include 引進來當作實體方法
extend 塞入幽靈空間成類別方法
程式碼
在Ruby有如果不是判斷式,格式如下
unless 條件式
.......
end
>>等同於if not 條件式
.....
end
當然也會有如果判斷式,格式如下
...... if 條件式 end
>>等同於 if 條件式 .... end
如果要針對不同條件做某事,在Ruby的格式比別家程式碼有些不同
case
when 條件
...
when 條件
...
else
...
end
>>類似於switch case
想要把顯示內容或是程式執行結果執行幾次,可以用times方法
數字.times{...}
數字.times 變數
在Ruby陣列有兩種,分別為Array.new和[],以下為新增範例
arr_new = Array.new(2,[0,0])
arr = [[0, 0], [0, 0]]
p arr==arr_new #true
看似相同但在改值後發生變化
arr_new[0][0] = "a"
p arr_new #[["a", 0], ["a", 0]]
arr[0][0] = "b"
p arr #[["b", 0], [0, 0]]
這是花生什麼事,為何Array_new不是改一個,於是我先把arr部分拿掉繼續測試
arr_new[1][0]="a"
p arr_new #[["a", 0], ["a", 0]]
代表前面[1]或[0]對他無動於衷,接著開始懷疑這東東
arr_new.each do |item|
p item.object_id
#70189242266200
#70189242266200
end
不會吧,竟然二維中哪個一維陣列都是指向同一個ID
因此在使用array new,別放集合類東西,才不會導致改值出現錯誤
array new,[]參考網址:http://stackoverflow.com/questions/4601652/ruby-array-creation-array-new-vs
在Ruby很常用each do方法把變數傳入陣列中
陣列.each do |變數|
puts "#{變數}"
end
也可以用以下方法得知index值
陣列.each_with_index do |變數|
puts "#{變數+1}" >>因為index以0開始,如要1開始要x+1
end
以前在學別家程式語言,難免會寫到Random,接著會是寫上100到200行之間指令,但在Ruby只有下面這行
p (1..52).to_a.sample(5)
p為輸出,(前數..後數)是Random範圍,to_a意思是轉成陣列,sample(數字)就是抽出幾個數字
然而在Ruby範圍有兩點和三點,但是意思卻天差地遠
(1..10) >>1~10
(1...10) >>1~9
?類似Id,回傳是布林值
def is_adult?(age)
age >= 18
end
if is_adult?(29)
puts "ok"
end
其實把問號刪掉,程式還是可以過,跟if運作一樣
def is_adult(age)
age >= 18
end
if is_adult(29)
puts "ok"
end
!會改變值,會把原本值改變,在運用上要特別小心
name = "eddie"
p name.upcase! #EDDIE
p name #EDDIE
其實把驚嘆號刪掉,程式還是可以過,但結果卻不一樣
name = "eddie"
p name.upcase #EDDIE
p name #eddie
?和!參考網址:http://zh.wikipedia.org/wiki/Rubyhttp://zh.wikipedia.org/wiki/Ruby
當我們僅打puts "hello",不禁好奇hello是算在哪個類別,這時可打以下這些
p "hello".class >>hello是在String的類別內
p "hello".class.superclass >>hello是在String,而String是在Object的類別內
p "hello".class.superclass.superclass >>hello是在String,而String是在Object,那Object是在BasicObject類別內
p self.class.private_methods.sort >>想知道self有哪些方法,以順排列顯示
以樹狀圖可知之間關係
BasicObject
|
Object
|
String
|
Hello
在別家程式語言常寫class,當然在Ruby也不例外
class 變數名稱 >>變數名稱以大寫開頭為class物件
...
end
至於繼承寫法倒是挺讓人意外
class 變數名稱 < 類別名稱 >>繼承
...
end
關於 < 他有看似很像的兄弟是 <<
class << self >>附加
其實這樣看可能不是很懂,那以陣列來說就很明顯
先設兩個陣列值,然後讓a附加b內容後顯示a
a=[1,2,3]
b=[4,5]
a << b
p a
結果為
[1,2,3,[4,5]]
<<參考網址:http://sls.weco.net/node/10732
在Ruby有初始值initialize,以下為範例
class Book
def initialize(name)
puts "hello, #{name}"
end
end
Book.new("eddie")
以下程式碼是把上方改成實體變數和顯示參數的go方法,透過實體化h把go方法實施
class Qa
def initialize(name)
@name=name
end
def go
@name <<等同於return @name
end
end
h=Qa.new("PP")
puts h.go
我們常用的三大public,protected,private,在Ruby卻有意外的是
private 呼叫不能有小數點
class Pri
def hello
secret_hi >>不能用self.secret_hi
end
private
def secret_hi
puts "gg"
end
end
g=Pri.new
g.hello
g.send(:secret_hi)
g.send(:send,:secret_hi)
但是在protected上可以接受小數點
class Pria
def hello
self.secret_hi
end
protected
def secret_hi
puts "gg"
end
end
g=Pria.new
g.hello
當然在public是允許使用小數點
class Priat
def hello
self.secret_hi
end
public
def secret_hi
puts "gg"
end
end
g=Priat.new
g.secret_hi
有時會把class留白,然後將他實體化(範例中h),接著用方法延伸,再來透過h.hi來執行方法
class Rabby
end
h=Rabby.new
def h.hi
puts "U0A0U"
end
h.hi
等同於
class Rabby
def hi
puts "U0A0U"
end
end
h=Rabby.new
h.hi
類別也是物件
class Rabby
end
def Rabby.hi
puts "U0A0U"
end
Rabby.hi
把上面改成下面這樣也能過,因為類別也是物件
class Rabby
def self.hi <<self指class的Rabby
puts "U0A0U"
end
end
Rabby.hi
puts 1.send(:+,2) <<Ruby 1+2=3
以下是我們取值和顯示的程式碼
class Ea
def get(name)
@name=name
end
def put
@name
end
end
h = Ea.new
h.get("LO")
puts h.put
如果每次都要寫取值顯示這兩個方法,其實是挺麻煩的(造成枯燥煩悶),於是Ruby多一個attr_accessor,讓變數可以付予寫和讀功能
class Ea
attr_accessor :name
end
h=Ea.new
h.name="LO"
puts h.name
以下是增加初始值寫法,會發現兩種不同結果
class Ea
attr_accessor :name <<可讀可寫
def initialize(name)
@name=name
end
end
h=Ea.new("Yo") <<initialize
puts h.name <<initialize getter
h.name="LO" <<setter
puts h.name <<getter
attr_accessor參考網址:http://stackoverflow.com/questions/4370960/what-is-attr-accessor-in-ruby
有時在特殊狀況我們會想用別號,以下是把+物件取為old_plus別號
class Fixnum
alias_method:old_plus,:+ <<別號方法:取別號,:物件名稱
def +(n)
self.old_plus(n)
end
end
p 1+1
既然有class,那當然少不了module這東西
module不能被繼承
module 模組名稱
...
end
以下是module的include範例
module Fly
def fly
puts "I can Fly!"
end
end
class Ani; end
class Bird < Ani
include Fly <<不是呼叫,而是把module內東西插入,實體方法
end
d=Bird.new
d.fly
在上方Fly這個module範例,不禁好奇一下這程式碼是如何運作,還有那些物件到底身在何處,所以我們可以用下面寫法去找到他
p class/module名稱.ancestors <<結構
p Bird.ancestors 顯示結果 [Bird,Fly,Ani,Object,Kernel,BasicObject]
p Fly.ancestors 顯示結果 [Fly]
既然有include,那也要提類似include但運作不一樣的extend
以下是module的extend範例
module Fly
def fly
puts "I can Fly!"
end
end
class Ani; end
class Bird < Ani
extend Fly <<塞入幽靈空間,類別方法
end
Bird.fly
從這兩個(include,extend)可知,包含執行是需要實體,但繼承執行不需要實體,不禁覺得extend和<真有異曲同工之妙
include和extend參考網址:http://www.railstips.org/blog/archives/2009/05/15/include-vs-extend-in-ruby/
p Class.instance_methods <<class結構方法
p Module.instance_methods <<module結構方法
搜尋Ruby Object Model可以找到關係圖
有時因為程式碼過長,怕會有重複名稱,我們能用::來指定(是這老爸帶的小孩)
module Do
class Doa
def awe
puts "food"
end
end
end
a=Do::Doa.new <<避免有重複Doa名稱於是用::,代表在Do底下Doa
a.awe
method_missing(,,,,) <<如果傳入參數找不到,顯示相關訊息
以下程式碼參考網址:http://ruby-doc.org/core-2.1.0/BasicObject.html
class MyObjectSystem < BasicObject DELEGATE = [:puts, :p] def method_missing(name, *args, &block) super unless DELEGATE.include? name ::Kernel.send(name, *args, &block) end def respond_to_missing?(name, include_private = false) DELEGATE.include?(name) or super end end
以下個人讀解: (可能有錯 ˊ ˇ ˋ)
一個名叫MyObjectSystem繼承BasicObject。
變數DELEGATE為陣列,存入puts和p標誌(標籤)。
宣告method_missing(傳入name和*arg和&block),
判斷傳入name變數在DELEGATE是否沒有包含,
沒有就根據之前運作顯示訊息,
有就Kernel送出傳入三個參數。
宣告respond_to_missing?(傳入name和include_private=false),
DELEGATE有包含此name變數或者根據之前運作顯示訊息。
後續,因為對*和&不解,於是我又跪拜Google大神求道
*在ruby doc上說明格式
ary * int → new_ary
ary * str → new_string
也舉了範例
[ 1, 2, 3 ] * 3 #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ] [ 1, 2, 3 ] * "," #=> "1,2,3"
&在ruby doc上說明格式
ary & other_ary → new_ary
也舉了範例
[ 1, 1, 3, 5 ] & [ 1, 2, 3 ] #=> [ 1, 3 ]
*和&在ruby doc參考網址:http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-2A
但是我還是解釋不出前面沒東東該作什麼
接著在某個問答論壇找到*解釋範例
def func2(arg1, arg2,*other_args) p arg1.inspect # => 1 p arg2.inspect # => 2 p other_args.inspect # => [3, 4, 5]
endfunc2(1,2,3,4,5)
從這可以得知*有擴展意思,所以當傳入值種類個數大於方法預定,可用*來加長
*問答參考網址:http://stackoverflow.com/questions/3701264/passing-a-hash-to-a-function-args-and-its-meaning
至於&我花長時間爬文終於找到,以下為修改後範例
class Array
def iterate2!(&code)
self.each_with_index do |n, i|
self[i] = code.call(n)
end
end
end
array = [1, 2, 3, 4]
array2 = [2, 2, 3, 4]
array.iterate2! do |n|
n ** 2
end
array2.iterate2! do |n|
n ** 2
end
puts array.inspect #[1, 4, 9, 16]
puts array2.inspect #[4, 4, 9, 16]
&在變數名稱前是宣告這是block參數,那block是啥鬼東西,於是用方法來問問這是哪種類別
def what_am_i(&block)
block.class
end
puts what_am_i {} #Proc
哇這Proc不就是SQL所學預存,沒錯,以下是用Proc範例
class Array
def iterate!(code)
self.each_with_index do |n, i|
self[i] = code.call(n)
end
end
end
array = [1, 2, 3, 4]
array2 = [2, 2, 3, 4]
square = Proc.new do |n|
n ** 2
end
array.iterate!(square)
array2.iterate!(square)
puts array.inspect #[1, 4, 9, 16]
puts array2.inspect #[4, 4, 9, 16]
後來我把*那個程式碼改成&
def func2(arg1, arg2,&other_args)
p arg1.inspect #1 #2
p arg2.inspect #2 #2
p other_args.inspect
# #<Proc:0x007f0b21aab670@text.rb:59>
# #<Proc:0x007f0b21aab418@text.rb:62>
end
func2(1,2) do #59行
#...
end
func2(2,2) do #62行
#...
end
原來proc內挖個block,0x開頭為記憶體位置,是block存在記憶體位置,記錄檔名叫text.rb,最後把執行行數也記錄,簡單來說proc內會存一或多block
那剛剛舉block和proc範例有何不同,其實看程式碼執行方式就知,proc是共用,但block可各走各的路((啥鬼說詞
像proc需創個實體square,array和array2透過實體square來實施iterate!,而實體都同個當然都是執行proc內定行程
但block不需創個實體,array和array2直接實施iterate!,而行程由各家歡樂定,讓人覺得自由過頭,不過也難怪會在proc class下
proc和&block參考網址:http://rubyer.me/blog/917/
留言列表