它爲什麼不起作用?因爲這不是Ruby的工作原理。同樣,這不起作用:
class Foo
def self.utility_method; ...; end
def inst_method
utility_method # Error! This instance has no method named "utility_method"
end
end
你可以變通的作法只是在做:
class MyClass
include HTTParty
def dosomething
HTTParty.base_uri("some_url")
end
end
讓我們來看看方法查找與模塊是如何工作的更深。首先,一些代碼:
module M
def self.m1; end
def m2; end
end
class Foo
include M
end
p Foo.methods - Object.methods #=> []
p Foo.new.methods - Object.methods #=> [:m2]
class Bar
extend M
end
p Bar.methods - Object.methods #=> [:m2]
p Bar.new.methods - Object.methods #=> []
class Jim; end
j = Jim.new
j.extend M
p j.methods - Object.methods #=> [:m2]
正如我們看到的,你可以使用extend
引起的對象(類或實例)使用模塊的「實例」方法對象本身(而不是實例),但是不能使模塊的「類方法」被任何東西繼承。你可以得到的最接近的是這個成語:
module M2
module ClassMethods
def m1; end # Define as an instance method of this sub-module!
end
extend ClassMethods # Make all methods on the submodule also my own
def self.included(k)
k.extend(ClassMethods) # When included in a class, extend that class with
end # my special class methods
def m2; end
end
class Foo
include M2
end
p Foo.methods - Object.methods #=> [:m1]
p Foo.new.methods - Object.methods #=> [:m2]
如果的HTTParty
模塊使用上面的圖案,因此提供了base_uri
方法對你MyClass
,那麼你可以做到這一點:
class MyClass
include HTTParty
def dosomething
self.class.base_uri("some_url")
end
end
...但這比直接引用擁有該方法的模塊更有用。
最後,因爲這可能對你有所幫助,下面是我幾年前製作的圖表。 (它缺少一些核心對象從Ruby 1.9的,像BasicObject
,但在其他方面仍然適用。點擊PDF版本。注意#3從圖中尤爲適用。)
Ruby Method Lookup Flow http://phrogz.net/RubyLibs/RubyMethodLookupFlow.png
感謝。 'HTTParty.get'在一個實例方法內工作,但'HTTParty.base_uri'不能。看起來像是因爲HTTParty定義了self.get而不是self.base_uri。那麼,我認爲這意味着無法爲不同的實例使用具有不同base_uri的HTTParty? – wadesworld 2012-07-19 22:02:26
@wadesworld base_uri在該類的單例類中設置該屬性。這意味着你不應該動態改變它,因爲你的代碼將不再是線程安全的。沒有什麼要求你設置base_uri,你可以在每個請求中指定URI。 – 2012-07-19 22:36:58
@wadesworld如[HTTParty :: ClassMethods#base_uri'的文檔](http://rdoc.info/github/jnunemaker/httparty/HTTParty/ClassMethods#base_uri-instance_method)所示,模塊使用確切的模式I如上所述。因此,該值存儲在類中,而不是實例中,您需要修改該庫或按需要重複更改每個實例的值。看到我上面的最後一個例子和這個評論中的鏈接是如何被設計使用的。 – Phrogz 2012-07-19 22:37:15