Ruby中方法名称的限制是什么?

例如,我发现方法名称bundler? 在下面的片段中,不知道是否是? 字符是专门的关键字或只是方法名称的一部分。

 # This is a predicate useful for the doc:guides task of applications. def bundler? # Note that rake sets the cwd to the one that contains the Rakefile # being executed. File.exists?('Gemfile') end 

Ruby中的方法名可能包含大写和小写字母,数字,下划线_和标点符号!?=

方法名称不能以数字开头,而且字符!?=只能出现在最后。

非ASCII字符可以在方法名称中使用,但是这会导致非常混乱的情况,不应该是常见的做法。

这是一个很好的做法,虽然不是强制性的,但用小写字母开始方法名,因为以大写字母开头的名字在Ruby中是常量。 对一个方法来说,仍然可以使用一个常量名,但是如果没有括号,你将无法调用它,因为interpeter会查找这个名字作为常量:

 def Capital nil end Capital # NameError: uninitialized constant Capital Capital() # => nil 

定义方法名称时,一些非常广泛和一贯使用的约定是:

  1. 方法名称全部为大写,下划线_表示分隔符(例如Math::sqrtArray#each_index ,…)。

  2. 谓词有一个问号? 作为最后一个字符(例如Array#empty?Hash#has_key? , …)。 虽然谓词通常返回布尔值,但并非总是如此:如果谓词的计算结果为false,则这些方法只需返回nil或false,否则返回任何其他值(例如,如果文件不存在, File::size?将返回nil ,否则为Integer的文件的大小)。

  3. 修改被调用对象的状态或者有不正常行为的方法有一个感叹号! 作为最后的字符; 这个方法有时被称为mutators,因为它们通常是破坏性的或其他方法的原地版本(例如Array#sort!Array#slice! …)。

  4. Setters有一个等号=作为最后一个字符(例如Array#[]= ,…); Ruby interpeter提供了调用setter方法的语法糖

     a = [4, 5, 6] a[0] = 3 # Shorthand for a.[]=(0, 3) 

Ruby还允许使用运算符符号定义运算符作为方法名称:

 ╔═══════════════════════════╦═════════════════════════════════════════════╦═══════╗ ║ Operators (by precedence) ║ Operations ║ Arity ║ ╠═══════════════════════════╬═════════════════════════════════════════════╬═══════╣ ║ ! ~ + ║ Boolean NOT, bitwise complement, unary plus ║ 1 ║ ║ ║ (define with method name +@, Ruby 1.9+) ║ ║ ║ ║ ║ ║ ║ ** ║ Exponentiation ║ 2 ║ ║ ║ ║ ║ ║ - ║ Unary minus (define with method name -@) ║ 1 ║ ║ ║ ║ ║ ║ * / % ║ Multiplication, division, modulo ║ 2 ║ ║ ║ ║ ║ ║ + - ║ Addition, subtraction ║ 2 ║ ║ ║ ║ ║ ║ << >> ║ Bitwise shift ║ 2 ║ ║ ║ ║ ║ ║ & ║ Bitwise AND ║ 2 ║ ║ ║ ║ ║ ║ | ^ ║ Bitwise OR, Bitwise XOR ║ 2 ║ ║ ║ ║ ║ ║ < <= => > ║ Ordering ║ 2 ║ ║ ║ ║ ║ ║ == === != =~ !~ <=> ║ Equality, pattern matching, comparison ║ 2 ║ ╚═══════════════════════════╩═════════════════════════════════════════════╩═══════╝ 

一元运算符方法不传递任何参数; 二元运算符方法传递一个参数,并对其进行操作。

严格遵守经营者的宗旨是很重要的。 虽然可以使用不同的参数定义运算符方法(例如,带有两个参数的+方法),但Ruby不允许使用运算符语法来调用方法(但它将使用点语法)。

尽可能地坚持操作符的原始语义是一个很好的习惯:对于那些知道操作符原来的意义的人来说,应该是直观的,它是如何与用户定义的类一起工作的。

该语言还为通常用于访问数组和散列值的特殊非运算符 []方法提供语法糖。 []方法可以用任意的arity来定义。

对于表中的每个二元运算符,除了sorting,相等,比较和模式匹配外,Ruby还提供缩写赋值的简写(例如, x += y展开为x = x + y )。 你不能将它们定义为方法,但你可以改变它们的定义它们所基于的操作符的行为。

这些字符在正常的方法名称中都不能使用(例如do&printstart-up不是有效的方法名称)。

别人说内置的语法是正确的,但是如果使用define_method + send类的方法,似乎没有什么后端的限制。

 define_method(:'$% ^&') { 0 } define_method(:'你好') { 1 } send(:'$% ^&') == 0 or raise send(:'你好') == 1 or raise 

这个事实可能是有用的:例如,Rails的ActiveSupport :: Testing :: Declarative.test方法使用它,以避免在以下方面进行复杂的转换:

 test 'Some Controller#Method' do 

到一个更清晰的名字,这可能会与另一个名为:

 test 'Some Controller_Method' do 

这在testing指南中提到。

好奇心:类似的事情发生在Java中,其中字节码方法名称比Java语言提供更多select: 为什么JVM允许我们命名以字节码中的数字开头的函数?

方法名称可以结束!?= 。 下划线也是允许的。 除此之外,还有几种看起来像运算符的方法(例如+*>>[] ),你可以为自己的类定义。

要添加一件事:你也可以告诉一个对象运行一个没有名字的方法,它将尝试调用一个名为call的方法:

 #!/usr/bin/env ruby class Foo =begin def call(*args) puts "received call with #{args.join(' ')}" end =end def method_missing(m, *args, &block) puts "received method_missing on `#{m}(#{args.join(', ')})`" end end f = Foo.new f.('hi') # Not a syntax error! method_missing with m of :call f.send :'', 'hmm' # method_missing with m set to :'' f.send nil, 'bye' # raises an error 

实际上并没有任何名为call方法定义在Object ,但MethodProc类中有一个。

在一些语言中()是函数调用的一个操作符,这和这里发生的事情很相似。

这是用在例如Rails的JBuilder中:

https://github.com/rails/jbuilder

它被logging在O'Reilly Ruby书籍的第196页上:

Ruby 1.9提供了一个调用Proc对象的方法。 作为方括号的替代方法,可以使用以句点为前缀的括号:

 z = f.(x,y) 

.()看起来像缺less方法名称的方法调用。 这不是一个可以定义的运算符,而是调用call方法的语法糖。 它可以与定义call方法的任何对象一起使用,并且不限于Proc对象。

允许的字符是: aZ, 0-9 ,只要不在开头, _? (用于布尔函数)和! (对于破坏性function)和= (对于设置者)。