使用Ruby的屬性
查看任何面向?qū)ο蟮拇a,它或多或少都遵循相同的模式。創(chuàng)建一個(gè)對(duì)象,調(diào)用該對(duì)象上的一些方法并訪問(wèn)該對(duì)象的屬性。在那里'除了將它作為參數(shù)傳遞給另一個(gè)對(duì)象's方法之外,您可以對(duì)一個(gè)對(duì)象做些什么。但是我們?cè)谶@里關(guān)心的是屬性。
屬性就像可以通過(guò)對(duì)象點(diǎn)符號(hào)訪問(wèn)的實(shí)例變量。例如,人物姓名 會(huì)訪問(wèn)一個(gè)人的名字。同樣,您可以經(jīng)常分配給類似的屬性人物姓名="Alice"。這與成員變量(如C++)類似,但不完全相同。在這里沒(méi)有什么特別之處,使用"getters"and"setters,"或從實(shí)例變量中檢索和設(shè)置屬性的方法,以大多數(shù)語(yǔ)言實(shí)現(xiàn)屬性。
Ruby沒(méi)有't區(qū)分屬性getter和setter以及正常方法。由于Ruby'靈活的方法調(diào)用語(yǔ)法,不需要區(qū)分。例如,人物姓名 和人物姓名()是同一件事,你'用零參數(shù)重新調(diào)用name方法。一個(gè)看起來(lái)像一個(gè)方法調(diào)用,另一個(gè)看起來(lái)像一個(gè)屬性,但它們'實(shí)際上都是同一件事。他們'都只是調(diào)用name方法。類似地,任何以等號(hào)(=)結(jié)尾的方法名稱都可以用于分配。聲明人物姓名=#34;Alice"與完全相同人物姓名=(alice),即使屬性名稱和等號(hào)之間有空格,它仍然只是調(diào)用name=方法。
01
of 03
自己實(shí)現(xiàn)屬性
您可以自己輕松實(shí)現(xiàn)屬性。通過(guò)定義集合ter和getter方法,您可以實(shí)現(xiàn)任何您希望的屬性。這里'是一些實(shí)現(xiàn)person類的name屬性的示例代碼。它將名稱存儲(chǔ)在@name實(shí)例變量中,但名稱不't必須相同。請(qǐng)記住,這些方法沒(méi)有什么特別之處。
#!防控新型冠狀病毒肺炎健康知識(shí)/usr/bin/env ruby class Person def initialization(name)@name=name end def name@name end def name=(name)@name=name end def say_Helloplaces"hello,#{@name}#34;end end
你要注意的一件事是,這是很多工作。它'很多輸入只是說(shuō)你想要一個(gè)名為name的屬性訪問(wèn)@name實(shí)例變量。幸運(yùn)的是,Ruby提供了一些方便的方法來(lái)為您定義這些方法。
02
77 of 03 78使用attr?reader,attr?writer和attr?accessor
模塊類中有三種方法可以在類聲明中使用。請(qǐng)記住,Ruby不區(qū)分運(yùn)行時(shí)和"編譯時(shí)間,"類聲明中的任何代碼不僅可以定義方法,還可以調(diào)用方法。調(diào)用attr?讀者,attr?writer和attr?accessor方法將反過(guò)來(lái)定義我們?cè)谏弦还?jié)中定義的setter和getter。
attr?閱讀器方法的效果就像它的聽(tīng)起來(lái)一樣。它采用任意數(shù)量的符號(hào)參數(shù),并且對(duì)于每個(gè)參數(shù),定義一個(gè)返回相同名稱的實(shí)例變量的"getter"方法。因此,我們可以用前一個(gè)示例中的name方法替換為attr?reader:name。
類似地,attr?writer方法為傳遞給它的每個(gè)符號(hào)定義一個(gè)"setter"方法。請(qǐng)注意,等號(hào)不一定是符號(hào)的一部分,而只是屬性名稱。我們可以代表將前一個(gè)示例中的name=方法放置為attr?writier:name。
正如預(yù)期的那樣,attr?accessor完成attr?writer和attr?reader的工作。如果您同時(shí)需要setter和getter來(lái)獲取屬性,通常的做法是不要分別調(diào)用這兩種方法,而是調(diào)用attr?u accessor。我們可以將前一個(gè)示例中的名稱和名稱=方法替換為attr?accessor:name。
#!/usr/bin/env ruby def person attr#accessor:name def initiate(name)@name=name end def say UHello puts"hello,#{@name}"end end
03
of 03
為什么要手動(dòng)定義Setters和getter?
為什么要手動(dòng)定義安裝器?為什么每次不使用attr方法?因?yàn)樗鼈兇蚱屏朔庋b。封裝是這樣的原則,即沒(méi)有外部實(shí)體應(yīng)該可以不受限制地訪問(wèn)對(duì)象的內(nèi)部狀態(tài)。應(yīng)使用防止用戶損壞對(duì)象內(nèi)部狀態(tài)的界面訪問(wèn)所有內(nèi)容。使用上述方法,我們'在封裝壁上打了一個(gè)大洞,并**允許為名稱設(shè)置任何東西,甚至顯然是無(wú)效的名稱。
您經(jīng)??吹降囊患率?em>attr?u reader將用于快速定義getter,但將定義自定義設(shè)置器,因?yàn)閷?duì)象的內(nèi)部狀態(tài)通常希望直接從內(nèi)部狀態(tài)讀取。然后手動(dòng)定義安裝器并檢查以確保設(shè)置的值是有意義的?;蛘?,也許更常見(jiàn)的是,根本沒(méi)有定義setter。類函數(shù)中的其他方法以某種其他方式在getter后面設(shè)置實(shí)例變量。
我們現(xiàn)在可以添加一個(gè)年齡,并正確實(shí)現(xiàn)名稱屬性。可以在constructor方法中設(shè)置age屬性,使用agegetter讀取,但僅使用have?broady方法操作,這將增加年齡。name屬性具有正常的getter,但setter確保名稱大寫,并采用Firstname Lastname的形式。
#!/usr/bin/env ruby類Person def初始化(姓名,年齡)self.name=name@age=age end attr#reader:name,:age def name=(newname)如果newname=?/^[A-Z][A-Z]+[A-Z]+$/@name=new#name-else"'#{new#name}'不是有效名稱!"結(jié)束定義有_生日放置"生日快樂(lè)#{@name}!"@age+=1 end def whoami put"你是#{@name},age#{@age}"end end p=人。新("Alice Smith",23)#誰(shuí)是我?p、 whoami#她結(jié)婚了p.name="Alice Brown"#她試圖成為一個(gè)偏心的音樂(lè)家p.name="A"#但失敗#她有點(diǎn)老了p.Harve#生日#我再次是誰(shuí)?p、 whoami