Ruby Guides
What is self, exactly? It’s a Ruby keyword that gives you access to the current object.
先看個在irb中的self
2.7.3 :100 > def coffee
2.7.3 :101 > puts self
2.7.3 :102 > end
=> :coffee
2.7.3 :103 > coffee()
main
=> nil
為何印出main?
答案是:Because it’s the name of the top-level object, it’s an object where you’ll find all the methods defined outside a class.
就結束了,問題這個top-level object到底在哪?
在這裡
2.7.3 :001 > is_a?Object
=> true
2.7.3 :002 > methods
=> [:irb_popb, :popb, :jobs, :fg, :source, :help, :inspect, :context, :kill, :exit, :to_s, :irb_quit, :quit, :irb_print_work.....略
Ruby for beginners
The top-level scope is an empty, anonymous object. All Ruby code starts in here.
簡單的說,當執行irb時,irb都會先開好一個最上層的匿名top-level object,可以直接定義一堆方法類別,或是輸入一堆資料,甚至開一個新.rb
檔,在運行前讓在irb中的物件暫時的"獨立存在",也是為何當離開重進後會一切需要從新輸入。
有更感覺到為何可以輸入什麼值,就馬上會回傳了嗎?
2.7.3 :003 > 50
=> 50
2.7.3 :004 > "50"
=> "50"
2.7.3 :005 > {}
=> {}
補充:先隨意定義一個method
,也可以用下面方式找到喔
2.7.3 :009 > methods.include?(:meth_name)
當self
在class裡時
class Ashen
attr_accessor :role
def initialize(name, role)
@name = name
@role = role
end
def one
puts self
end
def kill_gwyn
self.role = "薪王"
puts self
end
end
2.7.3 :078 > player = Ashen.new("Ash", "不死者")
=> #<Ashen:0x00007f8ef30d25f8 @name="Ash", @role="不死者">
2.7.3 :079 > player.one
#<Ashen:0x00007f8ef30d25f8>
=> nil
#與new出來時的時候記憶體編號相同。
2.7.3 :080 > player.kill_gwyn
#<Ashen:0x00007f8ef30d25f8>
=> nil
#與上面一樣
2.7.3 :082 > player.role
=> "薪王"
所有操作都是指向new出來的player
Access to the current object。
class Ashen
def self.say_something
puts "灰燼成雙,則火燃起"
puts self
end
end
2.7.3 :013 > Ashen.say_something
灰燼成雙,則火燃起
Ashen
=> nil
self.say_something
是定義類別方法
的一種寫法,可以看到puts self
印出的是類別Ashen
。
文字遊戲,Ashen
defself.say_something
,Ashen
定義自己說些什麼。Ashen.is_a? Object #=> true
無論如何self指的就是當前物件。
玩一下itself
2.7.3 :024 > 50.itself == Integer
=> false
2.7.3 :025 > 50.itself == 40
=> false
2.7.3 :026 > 50.itself == 50
=> true
2.7.3 :027 > 50.itself * 10
=> 500
2.7.3 :028 > [1, 2, 3].map{|num| num.itself.to_s}
=> ["1", "2", "3"]
判斷方式如self
,看是誰在用,真的就這麼簡單。
所以只介紹怎麼建立類別方法,一種上一段說了,現在講比較好整理的寫法。
昨天腳本有以下這段被標記起來的code。
class << self
def fake_new
Elden_ring.new("隱藏大魔王", "玩家", "unlimited")
end
end
直接改造一下。
class Elden_ring
def initialize(name = "殭屍", role = "反派", power = 20)
@name = name
@role = role
@power = power
end
class << self
def fake_new
Elden_ring.new("隱藏大魔王", "玩家", "unlimited")
end
end
end
2.7.3 :044 > me = Elden_ring.new
=> #<Elden_ring:0x00007fd511af6ca0 @name="殭屍", @role="反派", @power=20>
2.7.3 :045 > me.fake_new
Traceback (most recent call last):
NoMethodError (undefined method fake_new for #<Elden_ring:0x00007fd511af6ca0>)
2.7.3 :046 > Elden_ring.fake_new
=> #<Elden_ring:0x00007fd511af4d60 @name="隱藏大魔王", @role="玩家", @power="unlimited">
fake_new
只有Elden_ring
能用喔,因為是類別方法。
昨天的範本,將private
的註解取消後,在腳本區的ash.bad_name?(ash.name)
,就會馬上使檔案無法運行,會出現這樣的錯誤<main>': private method bad_name?' called for #<Elden_ring:0x00007fe03e179758> (NoMethodError)
。
不是寫在同一頁嗎?也沒有故意拆分兩個檔案(正確應該要分開...),為何還是顯示私有的?
原因是,private
讓方法只能在class的定義區內被使用。
反過來將ash.bad_name?(ash.name)
註解掉,發現又可以繼續正常運行腳本。
private寫法
class Mine
private
def under_private_is_mine
end
end
也可以這樣
class Mine
def some_methods
end
def i_am_private
end
private :i_am_private
end
由於網路上private
三兄弟資料非常多,這邊只補充一部分是,類別方法也可以private
。
2.7.3 :024 > Array.name
=> "Array"
2.7.3 :025 > Integer.name
=> "Integer"
class Test_list
def self.name
"中二"
end
end
2.7.3 :031 > Test_list.name
=> "中二"
不是指這種私有喔!
而是如一般方法的私有。
class Abc
def self.go_home
way
end
class << self
private
def way
puts "on my way!"
end
end
end
2.7.3 :014 > Abc.way #NoMethodError (private method `way' called for Abc:Class)
2.7.3 :015 > Abc.go_home
on my way!
=> nil
2.7.3 :016 > class Bcd < Abc
2.7.3 :017 > end
=> nil
2.7.3 :018 > Bcd.go_home
on my way!
=> nil
是的,類別方法可以私有,但看程式碼應該可以發現private
對class_methods
的繼承沒有限制效力。
這不是原理,這是原則
喔,不然怎麼物件導向,不然怎麼類別繼承。看過網路文章有人鑽牛角尖問這個問題,最後的回答是你應該去學其他語言
()
有時千萬不要省略。昨天code很明顯有一個地方是不該省略( )
的。
直接這邊改寫
2.7.3 :001 > bad_word = [1, 2, 3]
=> [1, 2, 3]
2.7.3 :002 > "123".split"" & bad_word == []
Traceback (most recent call last)
NoMethodError (undefined method `&' for "":String)
#依照提示修改
2.7.3 :003 > "123".split("") & bad_word == []
=> true
或是像我的醜寫法
2.7.3 :004 > ("123".split"") & (bad_word) == []
=> true
常常code突然跳NoMethodError (undefined method ...
,這類資訊,就該先檢查一下是不是()
在搞鬼了
另外還有要注意類似數學運算,執行權{}
優先權大於[]
大於()
。
sleep的用途。
暫停程式運行用,也可用在方法內喔。
def hi_and_hello
puts "hi"
sleep 2
puts "hello"
end
執行後會停止運作,不過進入Rails後,前端交給js,不大會再看到了。
記得帶參數,不要只有sleep()
gets.chomp()
這是看一本老書Learn Ruby The Hard Way
看到的,因為版本問題不會很推薦看這本書,但是偶爾看看可以發現很多老玩家
用的特殊寫法,那些在中文資料內比較不好找到。
gets
很明顯是抓取方法。irb可直接利用。
2.7.3 :014 > gets
輸入後會發現畫面換行但是沒動,不用擔心,代表可以開始輸入內容了。
2.7.3 :015 > gets
今天天氣很好,我想要出門去玩!
=> "今天天氣很好,我想要出門去玩!\n"
可以發現多了換行符號\n
,我們改輸入gets.chomp()
,()
可省略。
2.7.3 :026 > gets.chomp
今天天氣很好,我想要出門去玩!
=> "今天天氣很好,我想要出門去玩!"
chomp
作用是去除抓取字串最後面的跳脫字元。
2.7.3 :034 > gets.chomp
今天天氣\n很好
=> "今天天氣\\n很好"
在中間的沒用喔。
補充chop
2.7.3 :037 > "很重要".chop
=> "很重"
2.7.3 :038 > "很重".chop
=> "很"
2.7.3 :039 > "很".chop
=> ""
puts
你不用知道但知道比較酷的技巧?
**irb模式
與變成程式一部分再輸出
有時會有不一樣效果喔
主要說明於method內的puts
請用\n
def test_puts
puts "123\n456\n789"
end
2.7.3 :075 > test_puts()
123
456
789
#puts "123
#456
#789" 方法內這樣不會出事,比較不好看而已
想要""
內有""
或特殊符號,%{}
def test_puts
puts %{"1-9"~!@#$%^&*()_+-=}
end
2.7.3 :079 > test_puts()
"1-9"~!@#$%^&*()_+-=
%w()
=> 如果不想一直打""
def test_puts
string = %w(今天 天氣 有夠好 對不對)
puts string
end
2.7.3 :084 > test_puts()
今天
天氣
有夠好
對不對
puts <<-EOF ....... EOF
可以縮排效果
def test_puts
puts <<-EOF
一陣操作猛如虎
一看戰績零杠五
EOF
end
2.7.3 :122 > test_puts()
一陣操作猛如虎
一看戰績零杠五
%s
真的想不到什麼地方可以用了..因為有each呀
def test_puts
puts "%s\n%s" % ["一頓操作猛如虎","一問薪水二百五"]
end
=> :test_puts
2.7.3 :131 > test_puts()
一頓操作猛如虎
一問薪水二百五
def test_puts
strings = ["床前明月光", "疑似地上霜", "舉頭望明月", "低頭吃便當"]
strings.each{|string| puts string}
end
2.7.3 :136 > test_puts()
床前明月光
疑似地上霜
舉頭望明月
低頭吃便當
瞭解一些就好,設計師們會幫你煩惱這塊的....
這部分到Rails後,會被Migration
取代,畢竟連接著資料庫,需要更安全正確的手段才能動資料庫。
也更不應該隨便手動去更改資料庫的內容。
Has的key相對於每個column名稱,value相對於column的值。
在Ruby時我們有許多方式去更改其中的key或value。
2.7.3 :137 > id_1 = {:name => "索拉爾" , :role => "太陽戰士", :belief => "太陽長男", :power => 250}
=> {:name=>"索拉爾", :role=>"太陽戰士", :belief=>"太陽長男", :power=>250}
2.7.3 :140 > id_1[:name] = "獵龍者"
=> "獵龍者"
#改key
2.7.3 :146 > id_1 = {:name => "索拉爾" , :role => "太陽戰士", :belief => "太陽長男", :power => 250}
=> {:name=>"索拉爾", :role=>"太陽戰士", :belief=>"太陽長男", :power=>250}
2.7.3 :147 > id_1[:title] = id_1.delete :name
=> "索拉爾"
2.7.3 :148 > id_1
=> {:role=>"太陽戰士", :belief=>"太陽長男", :power=>250, :title=>"索拉爾"}
#加入新的key與值的其中一種方法。
2.7.3 :003 > h = {}
=> {}
2.7.3 :004 > h[:a]= 123
=> 123
2.7.3 :005 > h
=> {:a=>123}
2.7.3 :007 > h[:b] = 456
=> 456
2.7.3 :008 > h
=> {:a=>123, :b=>456}
解題的時,一些更改value與key的方法,都會是好方法,但記得到Rails後,不要這樣對待資料庫內的資料。
~~這段純屬碎碎念~
滿一週了,紀念性的來一題中等難度的吧!
今天的Leetcod462. Minimum Moves to Equal Array Elements II
就昨天那題的II,不小心點到,不小心剛好想起最佳開會距離這個議題。所以之後還是繼續Easy題XD
題目連結:https://leetcode.com/problems/minimum-moves-to-equal-array-elements-ii/
題目重點:隨意選一個加1或減1,其實就是解答。
# @param {Integer[]} nums
# @return {Integer}
def min_moves2(nums)
end
puts min_moves2([1,2,3]) #=2
puts min_moves2([1,10,2,9]) #=16
用[1, 2, 3]
就可以看到答案。變成一樣其實往中間跑最快。
2 = 3 - 1 #動一步
2 = 1 + 1 #動一步
1 + 1 = 2
換個例子[1, 5, 4]
#4是中位數
2.7.3 :016 > [1, 5, 4].sort!
=> [1, 4, 5]
#直接改變參數本體,之後直接計算,不用再多用到一個變數的記憶。
#往4跑
4 = 1 + 3 #動3步
4 = 5 - 1 #動1步
總共4步,記得有的是+,有的是-,+
用x軸來說等於與中心點的位置是負的,-
反之。明明講有正有負就好....
如果不相信這個原理,請想想兩個人見面是往面對面的方向跑快,還是往同一邊跑?
所以n個人,要見面,也是往中心點跑,但這題目中心點是固定的,在這n個人之中,所以選出n個人的中心點。
整理一下
nums.sort!.each
nums.sort!.map #用哪個都好,但是我用完each後直接改map,等等答案就會知道原因了。
muns.size/2 #中間值
|num| num - nums[muns.size/2]
#因為有正有負記得加Anti-Lock Brake System,開玩笑的.abs。
(|num| num - nums[muns.size/2]).abs # 每個都計算與中心點的絕對值
最後記得sum。
整理完如下
def min_moves2(nums)
nums.sort!.map do |num|
(num - nums[nums.size/2]).abs
end
nums.sum
end
def min_moves2(nums)
nums.sort!.map {|num|(num - nums[nums.size/2]).abs}.sum
end
今天的重點
1.Ruby中self的意思?
2.請說明類別方法or實體方法差異
3.Ruby中private的用法
Leetcod462. Minimum Moves to Equal Array Elements II
明天講繼承與模組。