diff --git a/lib/singleton.rb b/lib/singleton.rb index 07420d2..757b77e 100644 --- a/lib/singleton.rb +++ b/lib/singleton.rb @@ -112,7 +112,7 @@ def _dump(depth = -1) module SingletonClassMethods # :nodoc: def clone # :nodoc: - Singleton.__init__(super) + super.include(Singleton) end # By default calls instance(). Override to retain singleton state. @@ -121,31 +121,18 @@ def _load(str) end def instance # :nodoc: - return @singleton__instance__ if @singleton__instance__ - @singleton__mutex__.synchronize { - return @singleton__instance__ if @singleton__instance__ - @singleton__instance__ = new() - } - @singleton__instance__ + @singleton__instance__ || @singleton__mutex__.synchronize { @singleton__instance__ ||= new } end private def inherited(sub_klass) super - Singleton.__init__(sub_klass) + sub_klass.include(Singleton) end end class << Singleton # :nodoc: - def __init__(klass) # :nodoc: - klass.instance_eval { - @singleton__instance__ = nil - @singleton__mutex__ = Thread::Mutex.new - } - klass - end - private # extending an object with Singleton is a bad idea @@ -156,14 +143,19 @@ def append_features(mod) unless mod.instance_of?(Class) raise TypeError, "Inclusion of the OO-Singleton module in module #{mod}" end + super end def included(klass) super + klass.private_class_method :new, :allocate klass.extend SingletonClassMethods - Singleton.__init__(klass) + klass.instance_eval { + @singleton__instance__ = nil + @singleton__mutex__ = Thread::Mutex.new + } end end diff --git a/test/test_singleton.rb b/test/test_singleton.rb index b3c48bb..b08972b 100644 --- a/test/test_singleton.rb +++ b/test/test_singleton.rb @@ -94,6 +94,13 @@ def test_inheritance_works_with_overridden_inherited_method assert_same a, b end + def test_inheritance_creates_separate_singleton + a = SingletonTest.instance + b = Class.new(SingletonTest).instance + + assert_not_same a, b + end + def test_class_level_cloning_preserves_singleton_behavior klass = SingletonTest.clone @@ -101,4 +108,8 @@ def test_class_level_cloning_preserves_singleton_behavior b = klass.instance assert_same a, b end + + def test_class_level_cloning_creates_separate_singleton + assert_not_same SingletonTest.instance, SingletonTest.clone.instance + end end