注意: 類也是物件當前類
# 頂層的類為object,若在此定義方法則為object的例項方法
class myclass # class 開啟的myclass 即為當前類
def my_method # myclass為當前類
endend
class_eval 方法
class 限制: 需要知道類名
class_eval 不需要知道類名就能開啟當前類
module#class_eval會在已存在類的上下文中執行乙個塊
def add_method_to a_class # 此時當前類為object
a_class.class_eval do # 當前類變更 a_class
def test_a
'class_eval會修改當前類和self'
endend
endadd_method_to string
"a".test_a # => 'class_eval會修改當前類和self'
對比:
class:
開啟類需要指定類的名字,而且必須時常量
class 是作用域門,使用class會失去區域性繫結
module#class_eval:
任何代表類的變數都可以使用class_eval
class_eval使用的是**塊,扁平作用域,可以獲取區域性繫結
ruby 允許給單個物件增加乙個方法只對單個物件生效的方法-單例方法
str = 'this is a singleton_method'
def str.title?
str.update == str
endstr.title? # => false
str.methods.grep(/title?/) #=> [:title?]
str.singleton_methods #=> [:title?]
這一段**單獨為str新增乙個title? 方法,其他的物件是沒有這個方法的
單例方法也可以用object#define_singleton_method 來定義
類也是乙個物件類名只是常量
an_obj.a_method
aclass.a_class_method
類方法的呼叫和物件例項方法的呼叫語法是一樣的,所以類方法的實質就是: 類方法是乙個類的單例方法
attr_accessor 是乙個類(module類)的類方法當乙個模組引入這個模組的時候自動幫我們拓展出這個方法
示例: ruby 核心中的方法 attr_accessor
class myclass
def my_attribute=(value)
@my_attribute = value
enddef my_attribute
@my_attribute
endend
obj = myclass.new
obj.my_attribute= 'whj'
obj.my_attribute # => 'whj'
可以用 module#attr_*來定義訪問器
所有的attr_* 方法都定義在module中,不管self是類還是模組,都可以使用方法,像這樣的方法稱之為類巨集乙個物件的單例方法沒有存在obj中,因為obj不是乙個類,也沒有存在obj的類中,因為這樣obj類的所有例項都能共享這個單例方法
單件類是乙個物件特有的隱藏類如何進入單件類:object#class 會將元類隱藏起來
class的特需語法
class << an_obj
#do_something
end
如果想要獲得單件類的引用,需在離開作用域時返回self
obj = object.new
singleton_class = class < obj
self
endsingleton_class.class # => class
object#singleton_class 能夠獲取單件類的引用
單件類是物件的單件方法存放的地方
每個單件類只有乙個例項,而且不能被繼承
類擴充套件乙個class 引入乙個module時,只引入了module的例項方法,不會引入類方法
解決:將類方法當初乙個普通的例項方法,然後在class的單例類中引入這個module-類擴充套件
module mymodule
def a_method
"hello, whj"
endendclass myclass
class << self
include mymodule
endendmyclass.a_method # => 'hello, whj'
物件擴充套件module mymodule
def a_method
"hello, whj"
endendclass myclass
endobj = myclass.new
class << obj
include mymodule
endobj.a_method # => 'hello, whj'
包(gem)中的方法不能直接修改,希望能夠為這個方法附加乙個額外的屬性, 所有的客戶端都會自動獲得這個屬性module#alias_method 別名
class myclass
def my_method
'hello, whj'
endendalias_method :m, :my_method
obj = myclass.new
obj.my_nethod # => 'hello, whj'
obj.m # => 'hello, whj'
環繞別名
給方法重定義乙個別名
重定義這個方法
在新的方法中呼叫老的方法
細化包裝器
下包含包裝器 module#prepend (較常用)
prepend包含的模組會插入該類祖先鏈的下方, 意味著它可以重寫該類的同名方法
class myclass
def my_method
"a"end
endmodule mymodule
def my_method
"b" #也可以使用super 來繼承
endendmyclass.class_eval do
prepend mymodule
endobj = myclass.new
obj.my_method # => "b"
ruby元程式設計 類定義
1 類是乙個增強的模組,所以所有類定義中的特性都同樣適用於模組定義。2 ruby程式中總是存在乙個當前物件 self,類似地,也總有乙個當前類或模組存在,當定義乙個方法時,該方法將成為當前類的乙個例項方法。3 當通過class關鍵字開啟乙個類時,這個類就成為當前類。4 module class ev...
python 元類程式設計
裝飾器任何時候你定義裝飾器的時候,都應該使用 functools 庫中的 wraps 裝飾器來註解底層包裝函式.因為乙個普通裝飾器作用在某個函式上時,這個函式的重要的元資訊比如名字 文件字串 註解和引數簽名都會丟失。但是 wraps不會。import time from functools impo...
python 元類程式設計
getattr 方法可用來檢查乙個類中是否有乙個屬性,比如 class user def init self,name self.name name def getattr self,item print not find attr def main user user dog user.age i...