class C1
unless method_defined? :hello # Certainly, it's not correct. I am asking to find something to do this work.
def_method(:hello) do
puts 'Hi Everyone'
end
end
end
では、メソッドが定義されているかどうかを判断するにはどうすればよいでしょうか。
class C1
unless method_defined? :hello # Certainly, it's not correct. I am asking to find something to do this work.
def_method(:hello) do
puts 'Hi Everyone'
end
end
end
では、メソッドが定義されているかどうかを判断するにはどうすればよいでしょうか。
投稿したコードは、メソッドが定義されているかどうかを確認するのに問題なく機能します。Module#method_defined?
まさに正しい選択です。(バリアント、、もありModule#public_method_defined?
ますModule#protected_method_defined?
。Module#private_method_defined?
)問題は、への呼び出しにありますがdef_method
、これは存在しません。(それはと呼ばれModule#define_method
ます)。
これは魅力のように機能します:
class C1
define_method(:hello) do
puts 'Hi Everyone'
end unless method_defined? :hello
end
ただし、名前は事前にわかっていて、クロージャを使用しないため、を使用する必要はありません。代わりにキーワードをModule#define_method
使用できます。def
class C1
def hello
puts 'Hi Everyone'
end unless method_defined? :hello
end
または、私はあなたの質問を誤解していて、あなたは継承について心配していますか?その場合、Module#method_defined?
継承チェーン全体を歩くため、は正しい選択ではありません。その場合、またはそのいとこの1つ、またはを使用する必要があります。Module#instance_methods
これModule#public_instance_methods
は、スーパークラス/ミックスインのメソッドを含めるかどうかを指示するオプションの引数を取ります。(ドキュメントが間違っていることに注意してください。引数を渡さない場合、継承されたすべてのメソッドが含まれます。)Module#protected_instance_methods
Module#private_instance_methods
class C1
unless instance_methods(false).include? :hello
def hello
puts 'Hi Everyone'
end
end
end
これが私の提案が機能することを示す小さなテストスイートです:
require 'test/unit'
class TestDefineMethodConditionally < Test::Unit::TestCase
def setup
@c1 = Class.new do
def self.add_hello(who)
define_method(:hello) do
who
end unless method_defined? :hello
end
end
@o = @c1.new
end
def test_that_the_method_doesnt_exist_when_it_hasnt_been_defined_yet
assert !@c1.method_defined?(:hello)
assert !@c1.instance_methods.include?(:hello)
assert !@o.methods.include?(:hello)
assert !@o.respond_to?(:hello)
assert_raise(NoMethodError) { @o.hello }
end
def test_that_the_method_does_exist_after_it_has_been_defined
@c1.add_hello 'one'
assert @c1.method_defined?(:hello)
assert @c1.instance_methods.include?(:hello)
assert @o.methods.include?(:hello)
assert_respond_to @o, :hello
assert_nothing_raised { @o.hello }
assert_equal 'one', @o.hello
end
def test_that_the_method_cannot_be_redefined
@c1.add_hello 'one'
assert @c1.method_defined?(:hello)
assert @c1.instance_methods.include?(:hello)
assert @o.methods.include?(:hello)
assert_respond_to @o, :hello
assert_nothing_raised { @o.hello }
assert_equal 'one', @o.hello
@c1.add_hello 'two'
assert @c1.method_defined?(:hello)
assert @c1.instance_methods.include?(:hello)
assert @o.methods.include?(:hello)
assert_respond_to @o, :hello
assert_nothing_raised { @o.hello }
assert_equal 'one', @o.hello, 'it should *still* respond with "one"!'
end
end
RubyObjectクラスを見てください。methods
メソッドのリストを取得する機能と、特定のメソッドrespond_to?
をチェックする機能があります。したがって、次のようなコードが必要です。
class C1
def add_hello
unless self.respond_to? "hello"
def hello
puts 'Hi Everyone'
end
end
end
end
cone.hello #This would fail
cone.add_hello
cone.hello #This would work
Objectクラスには、メソッド「methods」があります:docs
class Klass
def kMethod()
end
end
k = Klass.new
k.methods[0..9] #=> ["kMethod", "freeze", "nil?", "is_a?",
# "class", "instance_variable_set",
# "methods", "extend", "__send__", "instance_eval"]
k.methods.length #=> 42