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?
这不是正确的选择,因为它走遍了整个继承链。在这种情况下,您将不得不使用Module#instance_methods
or 它的表亲之一Module#public_instance_methods
,Module#protected_instance_methods
or 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
查看Ruby Object 类。它具有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 类具有方法“方法”:文档
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