Mục đích của “!” và "?" ở cuối tên phương thức?


99

Đôi khi tôi thấy các phương thức trong Ruby có "?" và "!" ở cuối chúng, ví dụ:

name = "sample_string"
name.reverse
name.reverse!
name.is_binary_data?

Tôi đã tự hỏi mục đích của họ là gì? Chúng chỉ là lớp phủ theo cú pháp?


Câu trả lời:


160

Nó "chỉ là lớp phủ" để dễ đọc, nhưng chúng có ý nghĩa chung:

  • Phương pháp kết thúc bằng !việc thực hiện một số thay đổi vĩnh viễn hoặc tiềm ẩn nguy hiểm ; ví dụ:
    • Enumerable#sorttrả về một phiên bản được sắp xếp của đối tượng trong khi Enumerable#sort!sắp xếp nó tại chỗ.
    • Trong Rails, ActiveRecord::Base#savetrả về false nếu lưu không thành công, đồng thời ActiveRecord::Base#save!đưa ra một ngoại lệ.
    • Kernel::exitkhiến một tập lệnh thoát ra, trong khi Kernel::exit!làm như vậy ngay lập tức, bỏ qua bất kỳ trình xử lý thoát nào.
  • Các phương thức kết thúc bằng ?boolean , làm cho dòng mã thậm chí còn trực quan hơn giống như một câu - if number.zero?đọc như "nếu số bằng 0", nhưng if number.zerotrông thật kỳ lạ.

Trong ví dụ của bạn, name.reverseđánh giá là một chuỗi được đảo ngược, nhưng chỉ sau name.reverse!dòng thì namebiến mới thực sự chứa tên được đảo ngược. name.is_binary_data?trông giống như "là namedữ liệu nhị phân?".


22
Một lưu ý quan trọng là bạn chỉ nên có phương pháp bang nếu bạn cũng có phương pháp không bang tương ứng. Tiếng nổ được sử dụng để phân biệt phương pháp "đáng ngạc nhiên hơn" với phương pháp "ít ngạc nhiên hơn". Nếu bạn chỉ có một phương pháp, thì không cần phân biệt, và bạn không nên đặt tên nó bằng một tiếng nổ. Hãy xem Array#clear, chẳng hạn. Nó xóa mảng. Xóa mảng tự nhiên sẽ làm thay đổi nó. Không có gì đáng ngạc nhiên về điều đó, do đó, cái tên đã làm cho nó rõ ràng: không có tiếng nổ. Xem ruby-forum.com/topic/176830#773946 .
Jörg W Mittag

2
Thêm vào những gì @ JörgWMittag đã nêu, theo Hướng dẫn về phong cách Ruby : Tên của các phương thức có thể nguy hiểm (tức là các phương thức sửa đổi bản thân hoặc các đối số, thoát! (Không chạy các trình hoàn thiện như exit), v.v.) phải kết thúc bằng dấu chấm than nếu có một phiên bản an toàn của phương pháp nguy hiểm đó .
Tod Birdsall

2
Hãy cẩn thận, điều này không phải luôn luôn như vậy. Ví dụ: Ruby Array # concat docs.ruby-lang.org/en/2.0.0/Array.html#method-i-concat . Nơi bạn có thể bị cháy nặng là những thứ như MyActiveRecordModel.column_names.concat (...). Thay vào đó, bạn phải sao chép nó trước khi thực hiện concat.
wintondeshong


8

Trong Ruby ?, phương thức này sẽ trả về một boolean và phương thức này sẽ !sửa đổi đối tượng mà nó được gọi. Chúng ở đó để cải thiện khả năng đọc khi xem mã.


5

Ngược lại với - tôi cho là - phần lớn các ngôn ngữ lập trình ...

Ruby, các phương thức được phép kết thúc bằng dấu chấm hỏi hoặc dấu chấm than.

Theo quy ước, các phương thức trả lời câu hỏi (tức là Mảng # rỗng? Trả về true nếu bộ nhận trống) kết thúc bằng dấu hỏi.

Các phương thức tiềm ẩn “nguy hiểm” (tức là các phương thức tự sửa đổi bản thân hoặc các đối số, thoát! V.v.) theo quy ước kết thúc bằng dấu chấm than.

Từ: http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/ , Mục Tên phương pháp vui nhộn


1
Ngoài ra, phương thức kết thúc bằng ?được gọi là phương thức vị từ.
Waseem

1

Hãy cẩn thận, điều này không phải luôn luôn như vậy. Lấy ví dụ, Ruby Array # concat http://docs.ruby-lang.org/en/2.0.0/Array.html#method-i-concat .

Nơi bạn có thể bị bỏng nặng là một cái gì đó MyActiveRecordModel.column_names.concat([url]). Các lệnh gọi sau này liên quan đến MyActiveRecordModel sẽ cố gắng tìm kiếm một cột 'url' cho MyActiveRecordModel và ném.

Thay vào đó, bạn phải sao chép nó trước khi thực hiện concat. May mắn thay, bộ thử nghiệm của tôi đã bắt được cái này, nhưng .. hãy chú ý!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.