日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

从自己实现Ruby单例模式揭秘Ruby模块内幕

發布時間:2023/12/15 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从自己实现Ruby单例模式揭秘Ruby模块内幕 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

???? 從自己實現Ruby單例模式揭秘Ruby模塊內幕

緣起

整個故事要從某一天開始說起,那天,我看到一篇文章介紹了Ruby中實現單例模式的模塊。Singleton模塊,只要include? Singleton模塊,就可以為一個Ruby類添加單例功能。

我頗為驚奇,于是查看Singleton.rb源碼,洋洋灑灑幾百行,看不懂。做技術的都知道,遇到不理解的東西我們總是想探究清楚,否則必茶不思飯不想,夜不能寐。

于是,我就想到CSDN論壇問問Ruby高人,不料Ruby論壇總是系統維護中這個狀態,想到其他Ruby社區問問,但一想還是算了。我平常都不逛其他社區的。

于是,繼續鉆研,費了一晚上的時間,終有所獲。雖然沒有完全看懂Ruby核心庫中的Singleton模塊的源碼,但自己也鼓搗出了一個Singleton模塊出來。

并且對Ruby模塊和Ruby語言的本質有了更深的認識。

?

?

?

使用模塊類載入方法實現的單例模塊!

源代碼:

下面請大家直接看看我的簡單版的Singleton模塊的源代碼。

?

??? 單例模塊,存在的意義就是在模塊被載入類時,給類添加類方法和創建對象實例等

module?? Singleton

這個方法在模塊被載入類時調用,傳入的參數是? 類對象

def self.included(base)??

這個操作把另一個模塊直接添加到Class對象上。類對象上的方法就是類方法。

盡管模塊中的方法是模塊的實例方法。

??? base.extend(SingletonClass);

?????

??????? puts("Singleton? Include!");

創建類的實例,然后把類的new方法設為私有類方法,防止被調用

最后把類的實例存放到類的方法中。

??????? myInstance=base.new();

?? base.private_class_method :new

????? # private_class_method :new

??? base.setClass(myInstance);

??????

??????

?????? #createSingleton(base);

??????

??????

?

???? end

???

??????

?????? end

????

?? module? SingletonClass

這個模塊附加上去的類方法,把類實例保存在模塊的實例變量中。也就是目標類的類變量中。

??? def setClass(base)

??????? puts("setClass");

??????? @myClass=base;

???????

??????? return? @myClass;

????? end

???? 單例方法,僅僅返回類的保護實例變量。

?????? def instance()

??????? puts("instance");

??????

???????

??????? return? @myClass;

????? end

?

? end

?

?

?

class Test

?? include Singleton;

?#private_class_method :new

?????

? def say(val)

????? puts(val);

??? end

?

end

?

test=Test.instance();

test.say("sssssss");

#test=Test.new();? # fail

?

?

技術詳解

上面展示的Singleton模塊的源代碼,雖然代碼量不多,卻使用了很多Ruby的高級技術。很有教學意義。當然,如果直接拿去使用也沒有問題,雖然沒有官方的Singleton模塊功能強,卻一樣實現了單例模式。

?

通過模塊怎樣給類添加類方法

Singleton模塊的功能是,目標類通過

include Singleton;

這一行代碼,可以給自己的類添加一個類方法instance().

我們一般使用Module,是給Module定義一些實例方法,然后這些方法就會成為目標類的實例方法。

我們也可以給Module定義類方法。這些方法必須要通過

Module.方法名()調用。

試驗下來,我們發現,目標類上不能調用模塊的方法。

?

那怎么才能實現通過Module給目標類添加類方法呢?

?

我們知道,Ruby中類是類,但其實類也是一個對象,一個特殊的對象。

Ruby的類對象就是Class類的實例。因此,對象具有的所有特征,類對象也都有。

JavaJSC#都是如此的。

?

Ruby的類對象上的實例方法,不就是類的方法嗎?

鑒于此,我們想到,只要在類對象上添加實例方法,那么我們就可以給類添加類方法。

?

RubyJavaScript一樣,都可以給對象而不是類型動態添加方法。這樣就成了。

?

Ruby的類繼承體系

?????????? ObjectClass

???????? ……

????? BaseClass

????????? ^

????????? |

(SingletonClass)

???????? ^

???????? |???? 各個includeModule

?????? SomeClass

???????? ^????

???????? |

???? (SingletonClass)

???????? ^

???????? |

???? someObj

?

?

上面就是Ruby的繼承體系,獨特而又精妙。

Ruby可以實現動態增刪對象的成員,而不僅僅是動態增刪類的成員。

另一種具備此種神功的就是JavaScript。但是,Ruby內部實現這些強大功能的內部機制和JavaScript的機制是截然不同的。

可謂殊途同歸!

?

?

1,Ruby是單根結構的單繼承體系的語言,它的根基類是Object類。所有的類最后都繼承Object類,這和其他語言一樣。JavaC#JavaScriptSmallTalk等都是如此。

?

2Ruby的類可以包括多個模塊。通過

include ModuleName

?? 即可達到此種目的,這種技術叫做混入Mixin

?? 通過這種技術,使單繼承的Ruby達到了多繼承的效果。

??? JavaScript也可以實現混入Mixin技術。這個我以后有時間再說。

?

在方法查找時,是先查找類本身定義的方法,然后再查找引入的模塊中的方法。最后查找基類的方法。

?

3Ruby不僅可以使用反射技術實現動態增刪類型的成員,還可以動態增刪對象的成員。

也就是說,Ruby類的各個實例,可以在運行時具備完全不同的數據結構和方法、行為特征!

這種強大的特性,JavaScript也具備。

現在讓我們看看Ruby是怎樣做到這一點的。

Ruby的每一個類實例,都有一個單獨的特殊的類型,SingletonClass

??? (SingletonClass)

???????? ^

???????? |

???? someObj

?

注意,SingletonClass不是Singleton模塊,不是用于實現單例模式的那個冬冬。

Ruby的一個特殊特征就是,一切都是類。JavaScript的哲學是一切都是對象。

既然任何對象都從屬于一個唯一的類型,那么我們只要使用動態修改Ruby類的成員的技術修改這個SingletonClass的成員,就可以實現動態修改單個對象的成員了。

?

4,回到上面的Singleton模塊的例子,為什么我們要講Ruby動態修改單個對象的方法呢?因為我們要使用這種技術實現給Ruby的類增加類方法instance()

再看上面的Ruby的繼承圖,我們看到Ruby的類,本身也是Class類型的一個實例。因此,任何類也都是有SingletonClass的。

因此,只要我們給類的SingletonClass增加實例方法instance,那么這個類就有了實例方法instance。這樣,我們的類就有了類方法instance

上面,我們正是利用了Ruby的這一特性,通過模塊給目標類動態添加了類成員函數instance()

?

5,模塊的included方法。

module?? Singleton

這個方法在模塊被載入類時調用,傳入的參數是? 類對象

def self.included(base)?

?

??? 模塊的included方法,會在模塊被類include時執行,其參數就是目標類對象。這個方法就是我們通過模塊類操作目標類的入口點。

?

1)給類的SingletonClass添加模塊,從而給目標類添加instance()方法。

盡管模塊中的方法是模塊的實例方法。

??? base.extend(SingletonClass);

?????

??????? puts("Singleton? Include!");

?

2)創建類的實例,然后把類的new方法設為私有類方法,防止被調用

最后把類的實例存放到類的方法中。

??????? myInstance=base.new();

?? base.private_class_method :new

???

??? 現在,沒有人能夠再創建目標類的實例了!

3)保存我們的單例。

?base.setClass(myInstance);

?base.private_class_method : setClass

?

?

4)看看我們給目標類添加靜態方法的模塊。

? module? SingletonClass

這個模塊附加上去的類方法,把類實例保存在模塊的實例變量中。也就是目標類的類變量中。

??? def setClass(base)

??????? puts("setClass");

??????? @myClass=base;

???????

??????? return? @myClass;

????? end

???? 單例方法,僅僅返回類的保護實例變量。

?????? def instance()

??????? puts("instance");

??????

???????

??????? return? @myClass;

????? end

?

?

OK!大功告成了!

下回也許我會再寫一篇文章,比較一下同樣NBJavaScriptRuby的優劣。

?

總結

以上是生活随笔為你收集整理的从自己实现Ruby单例模式揭秘Ruby模块内幕的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。