2016-04-07 15 views
2

假設我們希望有人編寫自己的僞隨機方法。作爲編程練習。我們希望每次他們試圖解決內置了功能快捷在Array類中禁用隨機播放和樣本

到目前爲止的時間產生一個錯誤,這是我做了什麼:

ERROR_STRING_FOR_RANDOM = "Usage of built-in random generators is not allowed" 

methods_to_block = ["rand", "srand", "Random::rand", "Random::srand", 
"Random::seed", "Random::new", "Kernel::rand", "Kernel::srand", 
"Array::shuffle", "Array::shuffle!", "Array::sample"] 

methods_to_block.each do |method| 
    eval 
    """ 
    def #{method} 
    raise ERROR_STRING_FOR_RANDOM 
    end 
    """ 
end 

所以,它阻止隨機的,這些加薪一個錯誤:

rand 
srand 
Random.new.rand(18) 

但它不適用於數組的僞隨機方法。例如

[1,2,3].shuffle! 

仍然有效。爲什麼會發生這種情況,以及如何預防它?

回答

2

您可以打開類和替換要禁用的方法...

class Array 
    ERROR_STRING_FOR_RANDOM = "Usage of built-in random generators is not allowed" 
    RANDOM_METHODS = [:shuffle, :shuffle!, :select] 
    def rajarshi_random_error 
    raise ERROR_STRING_FOR_RANDOM 
    end 
    RANDOM_METHODS.each do |m| 
    define_method(m) {|*args| rajarshi_random_error } 
    end 
end 
+0

:)).............. ......... –

2

你的代碼是越來越錯誤

ArgumentError: wrong number of arguments (0 for 1..4) 

但對於其他類似的模塊功能,你可以這樣定義

methods_to_block = ["rand", "srand","seed", "sample", "shuffle!", "shuffle!"] 

方法應該看起來像

methods_to_block.each do |method| 
    define_method "#{method}" do 
    raise ERROR_STRING_FOR_RANDOM 
    end 
end 
#=> ["rand", "srand", "Random::rand", "Random::srand", "Random::seed", "Random::new", "Kernel::rand", "Kernel::srand", "Array::shuffle", "Array::shuffle!", "Array::sample"] 

現在,如果您致電

> srand 
RuntimeError: Usage of built-in random generators is not allowed 

> rand 
RuntimeError: Usage of built-in random generators is not allowed 

希望它會幫助你

如果你想堅持保持自己的方式

ERROR_STRING_FOR_RANDOM = "Usage of built-in random generators is not allowed" 

methods_to_block = ["rand", "srand", "Random::rand", "Random::srand", 
"Random::seed", "Random::new", "Kernel::rand", "Kernel::srand", 
"Array::shuffle", "Array::shuffle!", "Array::sample"] 


methods_to_block.each do |method| 
if method.split("::").size > 1 && method.split("::").first != "Kernel" 
class_name = method.split("::").first 
method_name = method.split("::").last 
er = <<ER 
class #{class_name} 
def #{method_name} 
raise ERROR_STRING_FOR_RANDOM 
end 
end 
ER 
eval(er) 
else 
define_method "#{method}" do 
raise ERROR_STRING_FOR_RANDOM 
end 
end 
end 

現在你可以得到所有

> srand 
RuntimeError: Usage of built-in random generators is not allowed 

> rand 
RuntimeError: Usage of built-in random generators is not allowed 

> [2,3,4,5].shuffle 
RuntimeError: Usage of built-in random generators is not allowed 
0

好的。這工作:

class Array 
    undef_method :sample, :shuffle, :shuffle! 
end 

使用範圍解析運算符是錯誤的想法開始。他們只是創建內部類的常量,而不是重新定義方法

同樣,適當的方法來禁用蘭特和函數srand看起來是這樣的:

module Kernel 
    undef_method :rand, :srand 
    class << self 
    undef_method :rand, :srand 
    end 
end 

class Random 
    undef_method :rand, :srand, :seed 
    class << self 
    undef_method :rand, :srand, :new 
    end 
end