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

sta*_*tor 44 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
Run Code Online (Sandbox Code Playgroud)

Alb*_*oni 76

在Ruby的方法名称可以包含大写和小写字母,数字,下划线_和punctation迹象!,?,=.

方法名称不能以数字和字符开头!,?并且=只能在结尾处出现.

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

使用小写字符启动方法名称是一种很好的做法,虽然不是强制性的,因为以大写字母开头的名称是Ruby中的常量.仍然可以为方法使用常量名称,但是如果没有括号,您将无法调用它,因为interpeter将查找名称作为常量:

def Capital
    nil
end

Capital    # NameError: uninitialized constant Capital
Capital()  # => nil
Run Code Online (Sandbox Code Playgroud)

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

  1. 方法名是全降的情况下,用下划线_作为分隔符的话到名称(例如Math::sqrt,Array#each_index...).

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

  3. 修改调用它们的对象的状态或具有异常行为的对象的方法将感叹号!作为最后一个字符; 这种方法有时被称为增变,因为它们通常是其他方法破坏或就地版本(例如Array#sort!,Array#slice!...).

  4. Setter=与最后一个字符具有相同的符号(例如Array#[]=,......); Ruby interpeter提供了用于调用setter方法的语法糖:

    a = [4, 5, 6]
    a[0] = 3    # Shorthand for a.[]=(0, 3)
    
    Run Code Online (Sandbox Code Playgroud)

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 ?
???????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

一元运算符方法没有参数传递; 二元运算符方法传递一个参数,并对其进行操作self.

严格遵守运营商的意见非常重要; 虽然可以使用不同的arity定义运算符方法(例如,一个带有+两个参数的方法),但Ruby不允许您使用运算符语法调用该方法(但它可以使用点语法).

最好尽可能地遵守运算符的原始语义:对于知道运算符的原始含义的人来说,它应该是直观的,它如何与用户定义的类一起工作.

语言还提供语法糖为特殊的,非操作者,[]是通常用于访问阵列和散列值的方法.该[]方法可以任意定义.

对于表中的每个二元运算符,除了排序,相等,比较和模式匹配,Ruby还提供缩写赋值的简写(例如,x += y扩展为x = x + y); 您不能将它们定义为方法,但您可以更改它们定义它们所基于的运算符的行为.

这些字符都不能在普通方法名称中使用(例如,do&print或者start-up不是有效的方法名称).


Cir*_*四事件 7

其他人说的内置语法是正确的,但是如果使用像define_method+ 这样的方法,似乎没有后端限制send:

define_method(:'$% ^&') { 0 }
define_method(:'??') { 1 }

send(:'$% ^&') == 0 or raise
send(:'??') == 1 or raise
Run Code Online (Sandbox Code Playgroud)

这个事实很有用:例如Rails的ActiveSupport :: Testing :: Declarative.test方法使用它,以便不对以下内容进行复杂的转换:

test 'Some Controller#Method' do
Run Code Online (Sandbox Code Playgroud)

更健全的名称,可能与另一个名为的测试冲突:

test 'Some Controller_Method' do
Run Code Online (Sandbox Code Playgroud)

这在测试指南中提到.

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