2012-05-10 15 views
40

Ví dụ: tôi đã tìm thấy tên phương thức bundler? trong đoạn mã sau và không biết liệu ký tự ? là từ khóa chuyên biệt hay chỉ là một phần của tên phương thức.Các hạn chế đối với tên phương thức trong Ruby là gì?

# 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 

Trả lời

72

Tên phương pháp trong Ruby có thể chứa chữ hoa và chữ thường, số, dấu gạch dưới _ và dấu chấm câu !, ?, =.

Tên phương thức không thể bắt đầu bằng số và các ký tự !, ?= chỉ có thể xuất hiện ở cuối.

Ký tự không phải ASCII có thể được sử dụng trong tên phương thức, nhưng điều này có thể dẫn đến các tình huống rất khó hiểu và không nên phổ biến.

Thực hành tốt, trong khi không bắt buộc, để bắt đầu tên phương thức có ký tự chữ thường, vì tên bắt đầu bằng chữ hoa là hằng số trong Ruby. Nó vẫn có thể sử dụng một tên liên tục cho một phương pháp, nhưng bạn sẽ không thể gọi nó mà không có dấu ngoặc đơn, vì interpeter sẽ nhìn-up cho cái tên như một hằng số:

def Capital 
    nil 
end 

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

Một số rất rộng rãi và luôn sử dụng ước khi xác định tên phương pháp là:

  1. tên phương có đầy đủ xuống hợp cụ thể, với dấu gạch _ như tách các từ vào tên (ví dụ Math::sqrt, Array#each_index, ...).

  2. vị từ có một dấu hỏi ? nhân vật như cuối cùng (ví dụ Array#empty?, Hash#has_key?, ...). Mặc dù các biến vị ngữ thường trả về giá trị boolean, nhưng các phương thức này chỉ cần trả về nil hoặc false nếu biến vị ngữ ước tính sai, bất kỳ giá trị nào khác (ví dụ: File::size? trả về nil nếu tệp không tồn tại, kích thước của dưới dạng Integer nếu không).

  3. Phương pháp sửa đổi trạng thái của đối tượng mà chúng được gọi hoặc có hành vi bất thường có dấu chấm than ! làm ký tự cuối cùng; các phương pháp này đôi khi được gọi là biến thể vì chúng thường là phiên bản phá hoại hoặc tại chỗ của các phương pháp khác (ví dụ: Array#sort!, Array#slice!, ...).

  4. Setters có dấu bằng = làm ký tự cuối cùng (ví dụ: Array#[]=, ...); các interpeter của Ruby cung cấp cú pháp đường cho invokation các phương pháp setter:

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

Ruby cũng cho phép xác định các nhà khai thác sử dụng các biểu tượng điều hành như tên phương pháp:

╔═══════════════════════════╦═════════════════════════════════════════════╦═══════╗ 
║ Operators (by precedence) ║     Operations     ║ Arity ║ 
╠═══════════════════════════╬═════════════════════════════════════════════╬═══════╣ 
║ ! ~ +      ║ Boolean NOT, bitwise complement, unary plus ║  1 ║ 
║       ║ (define with method name [email protected], Ruby 1.9+)  ║  ║ 
║       ║            ║  ║ 
║ **      ║ Exponentiation        ║  2 ║ 
║       ║            ║  ║ 
║ -       ║ Unary minus (define with method name [email protected]) ║  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 ║ 
╚═══════════════════════════╩═════════════════════════════════════════════╩═══════╝ 

phương pháp điều hành unary là không có đối số; các phương thức toán tử nhị phân được truyền vào một đối số và hoạt động trên nó và trên self.

Điều quan trọng là phải tuân thủ nghiêm ngặt tính chất của các nhà khai thác; trong khi có thể xác định các phương thức toán tử bằng một phép tính khác (ví dụ: phương thức + lấy hai đối số), Ruby sẽ không cho phép bạn gọi phương thức với cú pháp toán tử (tuy nhiên nó sẽ làm việc với cú pháp dấu chấm). Đó là thực hành tốt để tuân theo ngữ nghĩa ban đầu của các toán tử càng nhiều càng tốt: nó nên trực quan với người biết ý nghĩa ban đầu của toán tử cách nó hoạt động với các lớp do người dùng định nghĩa.

Ngôn ngữ cũng cung cấp cú pháp đường cho phương pháp đặc biệt, phi điều hành, [] thường được sử dụng để truy cập giá trị mảng và giá trị băm. Phương pháp [] có thể được xác định bằng tính chất tùy ý.

Đối với mọi toán tử nhị phân trong bảng, ngoại trừ thứ tự, bình đẳng, so sánh và đối sánh mẫu, Ruby cũng cung cấp cách viết tắt cho bài tập viết tắt (ví dụ: x += y mở rộng đến x = x + y); bạn không thể định nghĩa chúng như là các phương thức, nhưng bạn có thể thay đổi hành vi của chúng xác định các toán tử mà chúng dựa vào chúng.

Không thể sử dụng ký tự nào trong các tên phương thức thông thường (ví dụ: do&print hoặc start-up không phải là tên phương thức hợp lệ).

+1

Câu trả lời hay! Một lưu ý nhỏ: Nó là phong tục cho các phương thức dự báo (với một '?') Để trả về các giá trị falsey ('nil' hoặc' false') hoặc truethy (mọi thứ khác), không cần thiết 'true' và' false'. Giá trị trả về được sử dụng trong các câu lệnh 'if' khi nó hoạt động giống như nếu nó là' true' và 'false' nhưng giá trị trả về thực tế thường không phải là một phần của giao diện phương thức dự định, chỉ là thuộc tính truethy hoặc falsey. –

+0

Cảm ơn lời khuyên, tôi đã chỉnh sửa tương ứng. –

+0

Cũng có một số ký tự chỉ có thể được sử dụng làm tên toàn bộ phương thức, nghĩa là bạn có thể xác định các phương thức được gọi là - + * **/(nếu bạn đang quá tải các toán tử đó) chứ không phải phương thức gọi là foo + bar –

0

Các nhân vật cho phép là: a-Z,, 0-9 chừng nào không vào đầu, _, và ? (đối với chức năng boolean) và ! (đối với chức năng phá hoại) và = (ví setters).

2

Tên phương thức có thể kết thúc bằng !, ? hoặc =. Dấu gạch dưới cũng được cho phép. Bên cạnh đó có một số phương pháp giống như các toán tử (ví dụ: +, *, >>, []) mà bạn có thể xác định cho các lớp của riêng bạn.

4

gì người khác nói là đúng đối với việc xây dựng trong cú pháp, tuy nhiên có vẻ là không có hạn chế back-end trên những gì có thể được sử dụng nếu bạn sử dụng các phương pháp như define_method + send:

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

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

Thực tế này có thể có ích: ActiveSupport::Testing::Declarative.test phương pháp ví dụ Rails' sử dụng nó để không làm chuyển đổi phức tạp trên:

test 'Some Controller#Method' do 

để một tên saner, mà có thể xung đột với một thử nghiệm mang tên:

test 'Some Controller_Method' do 

Điều này được đề cập trên Testing Guide.

Curiosity: một điều tương tự xảy ra trong Java, nơi tên phương pháp bytecode cho sự lựa chọn cách hơn so với ngôn ngữ Java: Why does the JVM allow us to name a function starting with a digit in bytecode?

2

Để thêm một điều: bạn cũng có thể cho một đối tượng để chạy một phương pháp với không tên ở tất cả và nó sẽ cố gắng để gọi một phương thức có tên 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 

không có thực sự bất kỳ phương thức có tên call xác định trên Object, nhưng chỉ có một trên MethodProc lớp học.

Trong một số ngôn ngữ () là một toán tử cho lời gọi hàm và điều này có vẻ khá giống với những gì đang diễn ra ở đây.

Điều này được sử dụng, ví dụ: trong JBuilder Rails':

https://github.com/rails/jbuilder

Nó là tài liệu trên trang 196 của cuốn sách O'Reilly Ruby:

của Ruby 1.9 cung cấp thêm một cách để gọi một đối tượng Proc; thay thế cho dấu ngoặc vuông, bạn có thể sử dụng dấu ngoặc đơn được đặt trước bằng dấu chấm:

z = f.(x,y) 

.() trông giống như lời gọi phương thức thiếu tên phương thức. Đây không phải là toán tử có thể được định nghĩa, mà đúng hơn là cú pháp-đường gọi phương thức call. Nó có thể được sử dụng với bất kỳ đối tượng nào xác định phương thức call và không giới hạn đối tượng Proc.

Các vấn đề liên quan