2017-08-02 73 views
1

翻閱Rails代碼庫有時respond_to_missing?調用超級,有時不會。有沒有你不應該從respond_to_missing調用super的情況?紅寶石respond_to_missing?呼叫超級或不?

+0

你可能會提供一些代碼片斷,這兩種類型的行爲(當然鏈接到github)? –

+0

例如。 [ActiveSupport :: TimeWithZone](https://github.com/rails/rails/blob/cfb1e4dfd8813d3d5c75a15a750b3c53eebdea65/activesupport/lib/active_support/time_with_zone.rb)從respond_to調用超級?還有[respond_to_missing?](https://github.com/rails/rails/blob/cfb1e4dfd8813d3d5c75a15a750b3c53eebdea65/activesupport/lib/active_support/time_with_zone.rb#L503),但沒有。 [StringInquirer](https://github.com/rails/rails/blob/cfb1e4dfd8813d3d5c75a15a750b3c53eebdea65/activesupport/lib/active_support/string_inquirer.rb)更爲典型。 –

+0

常見模式是調用respond_to?在一個包裹的物體上跳過超級,例如。 [Duration#respond_to_missing?](https://github.com/rails/rails/blob/cfb1e4dfd8813d3d5c75a15a750b3c53eebdea65/activesupport/lib/active_support/duration.rb#L365) –

回答

1

它取決於類的實現以及您想要的#respond_to_missing?以外的行爲。看看ActiveSupport::TimeWithZone,它是Time的代理包裝。它試圖模仿它,愚弄你認爲它是Time的一個實例。例如,當通過Time時,TimeWithZone#is_a?將響應true

# Say we're a Time to thwart type checking. 
def is_a?(klass) 
    klass == ::Time || super 
end 
alias_method :kind_of?, :is_a? 

respond_to_missing?應該抓住將由method_missing被抓住的情況下,所以你必須看看這兩種方法。 TimeWithZone#method_missing代表丟失方法到Time而不是super

def method_missing(sym, *args, &block) 
    wrap_with_time_zone time.__send__(sym, *args, &block) 
rescue NoMethodError => e 
    raise e, e.message.sub(time.inspect, inspect), e.backtrace 
end 

是很有意義的,它會委託respond_to_missing?Time爲好。

# Ensure proxy class responds to all methods that underlying time instance 
# responds to. 
def respond_to_missing?(sym, include_priv) 
    return false if sym.to_sym == :acts_like_date? 
    time.respond_to?(sym, include_priv) 
end 
+0

同意。是否省略了||超級'在respond_to_missing結束?一個監督或一個故意的設計決定? –

+1

@PiersC對我來說,這看起來像一個蓄意的設計決定。他們希望它返回任何'時間'將返回。就像'method_missing'中沒有'super'一樣,他們只是讓'Time'找出如何處理它。班上一致的模式是,它試圖欺騙調用者認爲它是「時間」的一個實例。就好像這個班是猴子補丁一樣,根本不需要修改。 –

+0

@PiersC查看你的另一個例子'StringInquirer','method_missing'和'respond_to_missing?'調用'super',並且在相同的條件下如果'method_name [-1]!=「?」'。這似乎是一個合理的經驗法則,在大多數情況下'respond_to_missing?'應該反映'method_missing'。 –

1

respond_to_missing?作爲method方法的解決方案出現在Ruby 1.9.2版中。這裏有一個博客帖子大約是一個Ruby核心提交者:http://blog.marc-andre.ca/2010/11/15/methodmissing-politely/

之所以叫super然而,讓事件的邏輯返回false時,來電會冒泡的類層次結構Object返回false。如果你的類是實現respond_to_missing?的類的子類,那麼當你的邏輯返回false時,你會想要調用super。這通常是庫代碼的問題,而不是應用程序代碼。

+0

所以當你知道一個超類還實現'respond_to_missing? 「如果你不確定,打電話過來是否安全? –

+0

是的,如果你不確定它是安全的,因爲它會冒泡到'Object'類 – DiegoSalazar

+0

謝謝,很好的答案。 –