用于函数的Ruby模块

时间:2017-06-05 11:15:55

标签: ruby methods module

可以使用模块向类添加方法。如,

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 时,我想:

'

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

2 个答案:

答案 0 :(得分:1)

这可能是一个糟糕的主意。在运行时弄乱你的课程会让问题难以调试(我在那里调用那个方法的哪个版本?)而且你的代码难以理解(哦,对,我不能称之为那个方法因为它&# 39;尚未定义,我需要先调用此方法。

鉴于您在关于变量范围的问题结束时所说的话,我几乎可以肯定这不会解决您实际遇到的问题,我建议实际发布您的实际问题

也就是说,您提出的问题可以通过使用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

答案 1 :(得分: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,所以这只是raise一个NoMethodError

  

致电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一样,在Ruby中可以像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

或通过调用hook方法:

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
  

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

您的代码中没有变量,因此不可能有任何“问题”。