Project

General

Profile

Feature #14944

Support optional inherit argument for Module#method_defined?

Added by jeremyevans0 (Jeremy Evans) about 1 year ago. Updated about 1 year ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:88140]

Description

Module has many introspection methods for methods and constants that
either return an array or return true or false for whether the method
or constant is defined. Most of these methods support an optional
argument that controls whether to consider inheritance. Currently,
the following Module methods support such a argument:

  • const_defined?
  • constants
  • instance_methods
  • private_instance_methods
  • protected_instance_methods
  • public_instance_methods

and the following methods do not:

  • method_defined?
  • private_method_defined?
  • protected_method_defined?
  • public_method_defined?

This patch supports such an argument for the *method_defined?
methods.

While you can currently work around the lack of support via:

mod.instance_methods(false).include?(:method_name)

This patch allows the simpler and more efficient:

mod.method_defined?(:method_name, false)

One case where you want to exclude inheritance when checking
for a method definition is when you want to replace a method
that may already exist. To avoid a verbose warning, you want
to remove the method only if it is already defined:

remove_method(:foo) if method_defined?(:foo, false)
define_method(:foo){}

You can't call remove_method without checking for the method
definition, as that can raise a NameError, and you don't want
to include inheritance because remove_method will still raise
a NameError if the method is defined by an ancestor and not
by the module itself.


Files


Related issues

Related to Ruby master - Bug #15597: syscall not returning true from private_method_defined?RejectedActions

Associated revisions

Revision bccb24a8
Added by usa (Usaku NAKAMURA) about 1 year ago

Support optional inherit argument for Module#method_defined?

Module has many introspection methods for methods and constants that
either return an array or return true or false for whether the method
or constant is defined. Most of these methods support an optional
argument that controls whether to consider inheritance. Currently,
the following Module methods support such a argument:

  • const_defined?
  • constants
  • instance_methods
  • private_instance_methods
  • protected_instance_methods
  • public_instance_methods

and the following methods do not:

  • method_defined?
  • private_method_defined?
  • protected_method_defined?
  • public_method_defined?

This patch supports such an argument for the *method_defined?
methods.

While you can currently work around the lack of support via:

mod.instance_methods(false).include?(:method_name)

This patch allows the simpler and more efficient:

mod.method_defined?(:method_name, false)

One case where you want to exclude inheritance when checking
for a method definition is when you want to replace a method
that may already exist. To avoid a verbose warning, you want
to remove the method only if it is already defined:

remove_method(:foo) if method_defined?(:foo, false)
define_method(:foo){}

You can't call remove_method without checking for the method
definition, as that can raise a NameError, and you don't want
to include inheritance because remove_method will still raise
a NameError if the method is defined by an ancestor and not
by the module itself.

[ruby-core:88140] [Feature #14944]

From: Jeremy Evans code@jeremyevans.net

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64337 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 64337
Added by usa (Usaku NAKAMURA) about 1 year ago

Support optional inherit argument for Module#method_defined?

Module has many introspection methods for methods and constants that
either return an array or return true or false for whether the method
or constant is defined. Most of these methods support an optional
argument that controls whether to consider inheritance. Currently,
the following Module methods support such a argument:

  • const_defined?
  • constants
  • instance_methods
  • private_instance_methods
  • protected_instance_methods
  • public_instance_methods

and the following methods do not:

  • method_defined?
  • private_method_defined?
  • protected_method_defined?
  • public_method_defined?

This patch supports such an argument for the *method_defined?
methods.

While you can currently work around the lack of support via:

mod.instance_methods(false).include?(:method_name)

This patch allows the simpler and more efficient:

mod.method_defined?(:method_name, false)

One case where you want to exclude inheritance when checking
for a method definition is when you want to replace a method
that may already exist. To avoid a verbose warning, you want
to remove the method only if it is already defined:

remove_method(:foo) if method_defined?(:foo, false)
define_method(:foo){}

You can't call remove_method without checking for the method
definition, as that can raise a NameError, and you don't want
to include inheritance because remove_method will still raise
a NameError if the method is defined by an ancestor and not
by the module itself.

[ruby-core:88140] [Feature #14944]

From: Jeremy Evans code@jeremyevans.net

Revision 64337
Added by usa (Usaku NAKAMURA) about 1 year ago

Support optional inherit argument for Module#method_defined?

Module has many introspection methods for methods and constants that
either return an array or return true or false for whether the method
or constant is defined. Most of these methods support an optional
argument that controls whether to consider inheritance. Currently,
the following Module methods support such a argument:

  • const_defined?
  • constants
  • instance_methods
  • private_instance_methods
  • protected_instance_methods
  • public_instance_methods

and the following methods do not:

  • method_defined?
  • private_method_defined?
  • protected_method_defined?
  • public_method_defined?

This patch supports such an argument for the *method_defined?
methods.

While you can currently work around the lack of support via:

mod.instance_methods(false).include?(:method_name)

This patch allows the simpler and more efficient:

mod.method_defined?(:method_name, false)

One case where you want to exclude inheritance when checking
for a method definition is when you want to replace a method
that may already exist. To avoid a verbose warning, you want
to remove the method only if it is already defined:

remove_method(:foo) if method_defined?(:foo, false)
define_method(:foo){}

You can't call remove_method without checking for the method
definition, as that can raise a NameError, and you don't want
to include inheritance because remove_method will still raise
a NameError if the method is defined by an ancestor and not
by the module itself.

[ruby-core:88140] [Feature #14944]

From: Jeremy Evans code@jeremyevans.net

Revision 64340
Added by znz (Kazuhiro NISHIYAMA) about 1 year ago

Revert "Support optional inherit argument for Module#method_defined?"

Revision 64343
Added by usa (Usaku NAKAMURA) about 1 year ago

Fix problem about notimplemented case

Re-revert r64340, and take care about notimplemented case.

History

Updated by znz (Kazuhiro NISHIYAMA) about 1 year ago

If you want to suppress warnings, you can use undef_method instead of remove_method for the time being.

module M
  def foo; end
end
class C
  include M
  undef_method(:foo) if method_defined?(:foo)
  define_method(:foo){}
end

Updated by matz (Yukihiro Matsumoto) about 1 year ago

I think this is a good idea. Accepted.

Matz.

#3

Updated by usa (Usaku NAKAMURA) about 1 year ago

  • Status changed from Open to Closed

Applied in changeset trunk|r64337.


Support optional inherit argument for Module#method_defined?

Module has many introspection methods for methods and constants that
either return an array or return true or false for whether the method
or constant is defined. Most of these methods support an optional
argument that controls whether to consider inheritance. Currently,
the following Module methods support such a argument:

  • const_defined?
  • constants
  • instance_methods
  • private_instance_methods
  • protected_instance_methods
  • public_instance_methods

and the following methods do not:

  • method_defined?
  • private_method_defined?
  • protected_method_defined?
  • public_method_defined?

This patch supports such an argument for the *method_defined?
methods.

While you can currently work around the lack of support via:

mod.instance_methods(false).include?(:method_name)

This patch allows the simpler and more efficient:

mod.method_defined?(:method_name, false)

One case where you want to exclude inheritance when checking
for a method definition is when you want to replace a method
that may already exist. To avoid a verbose warning, you want
to remove the method only if it is already defined:

remove_method(:foo) if method_defined?(:foo, false)
define_method(:foo){}

You can't call remove_method without checking for the method
definition, as that can raise a NameError, and you don't want
to include inheritance because remove_method will still raise
a NameError if the method is defined by an ancestor and not
by the module itself.

[ruby-core:88140] [Feature #14944]

From: Jeremy Evans code@jeremyevans.net

#4

Updated by nobu (Nobuyoshi Nakada) 6 months ago

  • Related to Bug #15597: syscall not returning true from private_method_defined? added

Also available in: Atom PDF