[英]Ruby method with unusual syntax
我有一些方法:
def example_method
I ♥ world!
end
我對這個方法有兩個問題:
example_method
不是我的方法)。 'I ♥ too!'
沒有重新定義的字符串,覆蓋此方法。 第2點是我必須解決的練習。
謝謝!
Ruby的語法非常寬容。 當呈現abc
形式的元素時,它被解釋為鏈式方法調用: a(b(c))
因此,這意味着需要定義的方法a
其接受一個參數,另一b
接收一個參數,和一種方法c
它返回一些值。
c
部分應該是這樣的:
def world!
"too!"
end
然后你可以用另一種方法鏈接:
def ♥(x)
"♥ #{x}"
end
此方法名稱似乎不可能,但當前版本的Ruby確實允許方法名稱中的unicode字符。
最后一部分是類似的,留給你練習。
由於不存在引號,此方法如何不會返回錯誤(
example_method
不是我的方法)。
那么,怎么可能呢
puts foo
是不是SyntaxError
? 只是因為Ruby讓你省略了隱式接收器和消息發送中參數列表周圍的括號,所以這相當於
self.puts(foo)
無論如何,為什么還要引用? 引用是針對String
文字的,但除了Ruby中的String
文字之外還有很多其他內容,例如其他文字( Integer
, Float
, Hash
, Array
, Symbol
s),變量,消息發送等。
我的問題是,如何讓這種方法回歸
'I ♥ too!'
沒有重新定義的字符串,覆蓋此方法。
你嘗試過運行嗎? 錯誤消息不僅會回答您的問題#1,還會告訴您如何解決您的問題#2。
example_method
# NoMethodError: undefined method `world!'
好的,所以它告訴我們它找不到一個名為world!
的方法world!
。 我們可以做些什么來解決這個問題? 那么,定義一個怎么樣?
def world!; end
example_method
# NoMethodError: undefined method `♥'
太棒了,我們取得了進步! 現在它告訴我們它找不到名為♥
的方法。 所以,讓我們來定義!
def ♥; end
example_method
# ArgumentError: wrong number of arguments (given 1, expected 0)
# in `♥'
再次進步! Ruby希望我們知道♥
不接受任何爭論,但我們正在傳遞一個。 現在,讓我們忽略所有的論點。
def ♥(_) end
example_method
# NoMethodError: undefined method `I'
好吧,我們已經知道如何解決那個,不是嗎?
def I; end
example_method
# ArgumentError: wrong number of arguments (given 1, expected 0)
# in `I'
而且我們已經看到了一個:
def I(_) end
example_method
# => nil
看起來很有希望! 一切正常,我們只需修復返回值:
def I(_)
'I ♥ too!'
end
example_method
# => 'I ♥ too!'
而且,我們完成了!
請注意我們甚至不需要做任何實際工作來解決這個練習? 在Ruby的每一步都告訴我們確切的問題是什么,每次解決方案都是微不足道的:Ruby無法找到方法? 讓我們創造一個! Ruby甚至可以幫助我們告訴我們無法找到的方法的名稱,因此我們可以剪切並粘貼它。 Ruby告訴我們,我們正在將參數傳遞給一個不帶任何參數的方法? 讓我們在方法中添加一個參數,Ruby甚至可以幫助我們告訴我們方法的名稱以及需要添加的參數數量。 該方法返回錯誤的值? 只是讓它返回不同的東西!
好的,我們已經完成了,我們已經解決了這個問題。 但我們的解決方案是,由於缺乏一個更好的詞,“無聊”。 現在,一般,無聊還是不錯的 ,無聊的是簡單,枯燥的手段簡單,枯燥的手段,我們沒有做太多的思考,以創建代碼,這意味着任何人最終維護的代碼以后並不需要做的很多想法,這意味着當我們追逐錯誤時,我們不需要做太多思考(換句話說:我們不需要“追查”錯誤,它們會非常明顯並且正確地盯着我們臉)。
但在這種情況下,這是一種鍛煉 ,鍛煉是為了刺激我們。
所以,我們能做些什么? 我們有兩種方法( world!
和♥
)沒有做任何事情,我們有♥
和I
沒有使用的參數。 讓我們看看我們如何充分利用它們。
我們注意到句子的結構類似於example_method
中的代碼結構。 因此,一個想法是(不是I
只是簡單地返回整個句子)每個方法都負責只生成與其在代碼中的位置相對應的句子片段。 那么, world!
也回來'too!'
, ♥
返回'♥'
,然后I
返回'I'
:
def world!
'too!'
end
def ♥(_)
'♥'
end
def I(_)
'I'
end
example_method
# => 'I'
嗯......好吧,那不是我們想要的。 有什么問題? 啊,我們忘記了這些論點! 我們現在已經使用了兩個未使用的方法,但是我們仍然沒有使用我們未使用的參數。 所以,讓我們看看 - I
接受了一個論證, I
必須返回字符串'I'
后跟......某些東西......我們唯一可用的“東西”就是我們的論點。 讓我們試試如果我們返回字符串'I'
后跟參數會發生什么:
def I(rest)
'I' << rest
end
example_method
# => 'I♥'
那更好。 我們需要添加一個空格:
def I(rest)
'I ' << rest
end
example_method
# => 'I ♥'
當然,我們也需要句子的其余部分,但幸運的是我們在♥
方法中仍然有一個未使用的參數:
def ♥(rest)
'♥ ' << rest
end
example_method
# => 'I ♥ too!'
大! 我們現在有一個不再“無聊”的解決方案,它實際上利用了我們所有的方法和參數。 它甚至可以輕松擴展,例如,如果我們想讓它說'I ♥ YOU too!'
,我們只需做一個簡單的改變:
def YOU(rest)
'YOU ' << rest
end
I ♥ YOU world!
# => 'I ♥ YOU too!'
只有一件事困擾着我。 看看這三種方法:
def ♥(rest)
'♥ ' << rest
end
def I(rest)
'I ' << rest
end
def YOU(rest)
'YOU ' << rest
end
這確實看起來有點重復。 首先,該方法的名稱和字符串文字的值總是相同的,所以每一個方法中的重復,其次,所述的三種方法都非常相似,並具有相同的結構。
我們可以得到的方法中去掉重復的方法之一是使用Ruby的反射能力,通過使用來獲得訪問方法的體內方法的名稱Kernel#__callee__
方法 :
def ♥(rest)
"#{__callee__} #{rest}"
end
def I(rest)
"#{__callee__} #{rest}"
end
def YOU(rest)
"#{__callee__} #{rest}"
end
如您所見,現在這些方法不僅在結構上相似,而且完全相同。 我們可以通過動態合成方法來消除方法之間的重復,而不是明確地寫出每個方法:
%i[♥ I YOU].each do |method|
define_method(method) do |rest|
"#{__callee__} #{rest}"
end
end
那好多了! 不再重復了。
順便問一下,你注意到了什么嗎? 我忘了測試我們的方法仍然有效! 我們現在就這樣做, 始終在每一步 都進行測試!
example_method
# => 'I ♥ too!'
I ♥ YOU world!
# => 'I ♥ YOU too!'
Phew,一切仍然有效。
實際上,現在我們動態合成方法,不再需要使用Kernel#__callee__
反射方法,我們的循環知道方法的名稱:
%i[♥ I YOU].each do |method|
define_method(method) do |rest|
"#{method} #{rest}"
end
end
example_method
# => 'I ♥ too!'
I ♥ YOU world!
# => 'I ♥ YOU too!'
我們現在可以做的最后一件事是,而不是合成一組固定的方法,讓我們只回應某人向我們拋出的任何方法。 這就是method_missing
的用途:
def method_missing(method, rest)
"#{method} #{rest}"
end
example_method
# => 'I ♥ too!'
I ♥ YOU world!
# => 'I ♥ YOU too!'
I very much ♥ YOU world!
# => 'I very much ♥ YOU too!'
所以,這是我們所有重構結束時的完整代碼:
def example_method
I ♥ world!
end
def world!
'too!'
end
def method_missing(method, rest)
"#{method} #{rest}"
end
example_method
# => 'I ♥ too!'
I ♥ YOU world!
# => 'I ♥ YOU too!'
I very much ♥ YOU world!
# => 'I very much ♥ YOU too!'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.