元程式設計 類定義

2021-10-06 04:22:47 字數 3752 閱讀 7291

注意: 類也是物件

當前類
# 頂層的類為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...