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

dly7yett  于 2023-10-18  发布在  Ruby
关注(0)|答案(5)|浏览(122)

例如,我在下面的代码片段中发现了方法名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
c3frrgcw

c3frrgcw1#

Ruby中的方法名可能包含大写和小写字母、数字、下划线_和标点符号!?=
方法名不能以数字开始,字符!?=只能出现在末尾。
方法名中可以使用非ASCII字符,但这可能会导致非常混乱的情况,不应该成为常见的做法。
方法名以小写字符开头是一个很好的做法,虽然不是强制性的,因为在Ruby中以大写字母开头的名称是常量。仍然可以为方法使用常量名称,但是如果没有括号,您将无法调用它,因为interpeter将查找作为常量的名称:

def Capital
    nil
end

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

在定义方法名称时,一些非常广泛和一致使用的 * 约定 * 是:
1.方法名称是小写的,下划线_作为名称中单词的分隔符(例如,Math::sqrtArray#each_index,.)。
1.* predicate * 的最后一个字符是问号?(例如:Array#empty?Hash#has_key?,.)。虽然 predicate 通常返回布尔值,但情况并非总是如此:这些方法只需要返回nilfalse,如果 predicate 计算为false,否则返回任何其他值(例如,File::size?返回nil,如果文件不存在,则返回文件的大小,否则返回Integer)。
1.修改调用对象状态的方法,或者有异常行为的方法,最后一个字符是感叹号!;这种方法有时被称为 * mutator *,因为它们通常是其他方法的破坏性版本或原地版本(例如,Array#sort!Array#slice!,.)。
1.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 ║
╚═══════════════════════════╩═════════════════════════════════════════════╩═══════╝

一元运算符方法不传递任何参数;二元运算符方法传递一个参数,并对它和self进行操作。
严格遵守算子的性质是重要的;虽然可以定义具有不同arity的运算符方法(例如,一个+方法,它有两个参数),Ruby不允许你用运算符语法调用这个方法(但是它可以用点语法)。
最好的做法是尽可能地坚持操作符的原始语义:对于那些知道操作符的原始含义的人来说,它应该是直观的,它如何与用户定义的类一起工作。
该语言还为特殊的 * 非运算符 * []方法提供了语法糖,该方法通常用于访问数组和散列值。[]方法可以任意定义。
对于表中的每个二元运算符,除了排序,相等,比较和模式匹配,Ruby还提供了缩写赋值的简写(例如,x += y扩展为x = x + y);你不能将它们定义为方法,但是你可以通过定义它们所基于的操作符来改变它们的行为。
这些字符都不能用在普通的方法名中(例如,do&printstart-up不是有效的方法名称)。

h5qlskok

h5qlskok2#

其他人所说的对于内置语法是正确的,但是如果你使用像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

测试指南中提到了这一点。
Currency:类似的事情发生在Java中,字节码方法名称比Java语言提供了更多的选择:Why does the JVM allow us to name a function starting with a digit in bytecode?

xu3bshqb

xu3bshqb3#

方法名可以以!?=结尾。也允许使用下划线。除此之外,还有几个看起来像运算符的方法(例如,+*>>[]),您可以为自己的类定义这些类。

aoyhnmkz

aoyhnmkz4#

补充一点:你也可以告诉一个对象运行一个 * 没有名字 * 的方法,它会尝试调用一个名为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

Object上实际上没有定义任何名为call的方法,但在MethodProc类上有一个。
在某些语言中,()是函数调用的操作符,这似乎与这里发生的事情非常相似。
这是使用例如。Rails的JBuilder:
https://github.com/rails/jbuilder
这在O 'Reilly Ruby书的第196页有记载:
Ruby 1.9提供了一种额外的方法来调用Proc对象;作为方括号的替代方法,您可以使用带句点前缀的括号:

z = f.(x,y)

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

n3schb8v

n3schb8v5#

允许的字符为:a-Z,0-9只要不是在开始,_,和?(对于布尔函数)和!(对于破坏性函数)和=(对于setter)。

相关问题