This article is the 20th day article of Ruby Part 2 Advent Calendar 2020. https://qiita.com/advent-calendar/2020/ruby2
In Ruby, you can define a method with any name.
...... Speaking of "No, no,def $%^&*
I can't write it. ""||
Isn't it an operator that can't be redefined? " Both are correct, but Ruby still allows you to define a method with any name.
Let's take a closer look at what that means.
def
syntaxUse the def
syntax to define methods in Ruby.
#foo method definition
def foo
end
#After the method name!Or?Can be attached
def foo!
end
def foo?
end
# =You can use it like a setter by defining the method name at the end
def foo=(value)
end
#Uppercase letters are also ok
def FOO
end
#Hiragana etc. are also ok
def Hoge
end
#Keywords are also ok
def def
end
#Some operators can be redefined
class Integer
# 42 -3 is 42+Turn into 3!
def -(right)
self + right
end
#unary+Method definition
def +@
end
end
And both of the codes given in the first example will result in a Syntax Error.
# Syntax Error
def $%^&*
end
# Syntax Error
def ||
end
However, there is a way to define methods with these names. It's the define_method
method.
define_method
methodFirst, let's briefly explain the define_method
method.
The define_method
method, as the name implies, is a method for defining a method.
Often used to dynamically construct method names or define multiple similar methods at the same time.
`name`Define method name with capital letters
define_method(name.upcase) {}
# foo, bar,Define baz at once
%i[foo bar baz].each do |name|
define_method(name) { name }
end
Anddefine_method
Accepts any name. In other words$%^&*
Or||
You can also define a method with a name like.
These methods cannot be called with a Syntax Error when calling a method using .
, but they can be called using the __send__
method.
#Method definition
define_method('$%^&*') { puts 'method name is $%^&*' }
define_method('||') { puts 'method name is ||' }
#call
__send__ '$%^&*' # => method name is $%^&*
__send__ '||' # => method name is ||
But even||
Even if you define a method||
The behavior of the operator does not change.
class FalseClass
#False even if redefined||The result of something does not change
define_method('||') do
false
end
end
p false || true # => true
Of course, you can use the following method names that you can't really define.
define_method('') { puts 'Empty string is also ok' }
__send__ '' # =>Empty string is also ok
#Any byte from 0x00 to 0xff is ok
# (Kernel is included in class C.#To not redefine p)
class C
(0x00..0xff).each do |n|
define_method(n.chr) { pp n.chr }
end
end
C.new.__send__ 0x00.chr # => "\x00"
#It's okay to try defining a method with a random byte sequence
require 'securerandom'
class C2
10.times do
define_method(SecureRandom.random_bytes(10)) do
end
end
end
p C2.instance_methods(false)
# => [:"4(c\xF4\xBDQ\xD7\xB6\xA0l", :"J&q\xEEZ\x0E\xE3\x9F\"\xC1", :"}\x9F\xCF\x1C\x90\x06o\xFD\x84\xD6", :"U\x8Bc02'\xB4\xF0\xA0\xC4", :"\xEE\x88v\x14\xBA&j\xBE<\x10", :"\a+,\xCD\"\xF4\x83\x80\xE5\xCA", :"4\xC8\xAB/2\x06\f\xF1\xFB\xFA", :"\xBA\xE2E;\xCE\xBC\xB8\xB0b\xD0", :"u [l^q%\xC9\x03\xA2", :"q\xC5O\xAF\xDB\x05t\x86!\x88"]
In Ruby, you can use the define_method
method to define a method with any method name.
I think it's a technique you don't use very often, but it might be useful somewhere to remember.
Recommended Posts