2017-06-05 56 views
-2

可以使用模块将方法添加到类中。例如,用于功能的Ruby模块

class Test 
    include Singleton 
end 

是否可以使用相同的方法?例如,

class Test 
    include Singleton 

    def test 
    include Instructions_to_add_to_the_method 
    puts 'done' 
    end 
end 

其中:

module Instructions_to_add_to_the_method 
    puts 'hi !' 
end 

当调用Test.instance.test,我想:

hi ! 
done 

我不想调用另一个方法,因为它会给我带的范围问题我的变数。

+0

不,这不是红宝石的工作原理。模块不是宏。如果这就是你想要实现的目标,你可以使用'Module#prepend'或'Module#include'与'super'结合使用? –

回答

1

有可能增加方法到使用模块的类。例如,

class Test 
    include Singleton 
end 

号这并不 “添加方法一类”。 include只是使Singleton的超类Test。而已。没有什么是“添加到课堂”的。这只是继承。

是否可以使用相同的方法?例如,

class Test 
    include Singleton 

    def test 
    include Instructions_to_add_to_the_method 
    puts 'done' 
    end 
end 

没有方法Test#include,因此这将只是一个raiseNoMethodError

当调用Test.instance.test,我想:

hi ! 
done 

这就是继承是:

class Test 
    include Singleton 

    def test 
    super 
    puts 'done' 
    end 
end 

module Instructions_to_add_to_the_method 
    def test 
    puts 'hi' 
    end 
end 

class Test 
    include Instructions_to_add_to_the_method 
end 

Test.instance.test 
# hi 
# done 

注意在Ruby中使用继承的方式是有点落后。如果你真的需要这样的东西,你应该使用Beta这样的语言,这是继承如何自然发挥作用。

更好的解决方案会是这样的Template Method Software Design Pattern它在红宝石可以像yield简单荷兰国际集团以一个块的内容:

class Test 
    include Singleton 

    def test 
    yield 
    puts 'done' 
    end 
end 

Test.instance.test { puts 'hi' } 
# hi 
# done 

或采取Proc作为参数:

class Test 
    include Singleton 

    def test(prc) 
    prc.() 
    puts 'done' 
    end 
end 

Test.instance.test(-> { puts 'hi' }) 
# hi 
# done 

或通过调用挂钩方法:

class Test 
    include Singleton 

    def test 
    extension_hook 
    puts 'done' 
    end 

    def extension_hook; end 
end 

class HookedTest < Test 
    def extension_hook 
    puts 'hi' 
    end 
end 

HookedTest.instance.test 
# hi 
# done 

我不想调用另一种方法,因为它会给我变量的范围带来问题。

代码中没有变量,所以不可能有任何“问题”与他们。

+0

非常感谢答案,看来我对Ruby类继承的理解有点偏离 –

1

这可能是一个可怕的想法。在运行时弄乱你的类会使问题难以调试(我在那里调用哪种版本的方法?),而且你的代码很难遵循(哦,对,我还不能调用该方法,因为它尚未定义,我需要首先调用这个方法)。

鉴于你在变量范围界定问题的结尾所说的话,我几乎可以肯定,这不会解决你实际存在的问题,而且我建议实际发布你的实际问题。

这就是说,你问的问题可以通过使用includedextended钩来回答这,勿庸置疑,火当一个模块被包括和扩展:


module FooModule 
    def self.included(base) 
    puts 'FooModule included' 
    end 

    def self.extended(base) 
    puts 'FooModule extended' 
    end 
  
    def new_method 
    puts 'new method called' 
    end 
end 

class Extender 
    def test_extend 
    self.extend FooModule 
    puts 'done' 
    end 
end 

class Includer 
    def test_include 
    self.class.include FooModule 
    puts 'done' 
    end 
end 

t1 = Extender.new 
t2 = Extender.new 
t1.test_extend # Prints out "FooModule extended" followed by "done" 
t1.new_method # Prints out "new method called" 
t2.new_method rescue puts 'error' # Prints out "error" - extend only modifies the instance that calls it 

t1 = Includer.new 
t2 = Includer.new 
t1.test_include # Prints out "FooModule included" followed by "done" 
t1.new_method # Prints out "new method called" 
t2.new_method # Prints out "new method called" - all past and future instances of Includer have been modified