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
So, how to judge whether a method has defined or not?
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
So, how to judge whether a method has defined or not?
The code you posted works just fine for checking whether the method is defined or not. Module#method_defined?
is exactly the right choice. (There's also the variants Module#public_method_defined?
, Module#protected_method_defined?
and Module#private_method_defined?
.) The problem is with your call to def_method
, which doesn't exist. (It's called Module#define_method
).
This works like a charm:
class C1
define_method(:hello) do
puts 'Hi Everyone'
end unless method_defined? :hello
end
However, since you already know the name in advance and don't use any closure, there is no need to use Module#define_method
, you can just use the def
keyword instead:
class C1
def hello
puts 'Hi Everyone'
end unless method_defined? :hello
end
Or have I misunderstood your question and you are worried about inheritance? In that case, Module#method_defined?
is not the right choice, because it walks the entire inheritance chain. In that case, you will have to use Module#instance_methods
or one of its cousins Module#public_instance_methods
, Module#protected_instance_methods
or Module#private_instance_methods
, which take an optional argument telling them whether to include methods from superclasses / mixins or not. (Note that the documentation is wrong: if you pass no arguments, it will include all the inherited methods.)
class C1
unless instance_methods(false).include? :hello
def hello
puts 'Hi Everyone'
end
end
end
Here's a little test suite that shows that my suggestion works:
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 [email protected]_defined?(:hello)
assert [email protected]_methods.include?(:hello)
assert [email protected]?(:hello)
assert [email protected]_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
Look at the Ruby Object class. It has a methods
function to get an list of methods and a respond_to?
to check for a specific method. So you want code like this:
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
method_defined?
is just fine, the problem is that he misspelled define_method
. 2) respond_to?
doesn't check for a specific method, it checks whether an object responds to a specific message. (Hint: the name sorta gives it away, don't you think?) Understanding the difference between methods and messages is fundamental to understanding Ruby and even OO in general. 3) In your code, you check whether the class object C1
responds to :hello
, and based on that you define a hello
method for instances of C1
. ... –
Fabricant respond_to?
in an instance method (add_hello
), so it does check the instance (and not the class). Also, just out of curiosity, what is the difference between sending a message and invoking a method in Ruby? :) –
Emplace The Object class has the method "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
© 2022 - 2024 — McMap. All rights reserved.
test_that_the_method_cannot_be_redefined
andtest_that_the_method_does_exist_after_it_has_been_defined
fail under ruby 1.8.7. – Vacillating