Câu trả lời:
Nó được gọi là Toán tử điều hướng an toàn. Được giới thiệu trong Ruby 2.3.0, nó cho phép bạn gọi các phương thức trên các đối tượng mà không cần lo lắng rằng đối tượng có thể là nil
(Tránh undefined method for nil:NilClass
lỗi), tương tự như try
phương thức trong Rails .
Vì vậy bạn có thể viết
@person&.spouse&.name
thay vì
@person.spouse.name if @person && @person.spouse
Từ Tài liệu :
my_object.my_method
Điều này sẽ gửi tin nhắn my_method đến my_object. Bất kỳ đối tượng nào cũng có thể là người nhận nhưng tùy thuộc vào khả năng hiển thị của phương thức, việc gửi tin nhắn có thể tăng NoMethodError.
Bạn có thể sử dụng &. để chỉ định một người nhận, sau đó my_method không được gọi và kết quả là không khi người nhận không. Trong trường hợp đó, các đối số của my_method không được đánh giá.
Lưu ý: Mặc dù @Santosh đã đưa ra câu trả lời rõ ràng và đầy đủ, tôi muốn thêm một số thông tin cơ bản và thêm một lưu ý quan trọng liên quan đến việc sử dụng nó với các biến không phải là cá thể.
Nó được gọi là " Toán tử điều hướng an toàn " ( còn gọi là "Toán tử xích tùy chọn", "Toán tử không có điều kiện", v.v. ). Matz dường như gọi nó là "nhà điều hành cô đơn". Nó được giới thiệu trong Ruby 2.3 . Nó chỉ gửi một phương thức cho một đối tượng nếu không nil
.
# Call method `.profile` on `user` only if `user` is not `nil`
@user&.profile
# Equivalent to
unless @user.nil?
@user.profile
end
Xin lưu ý, mã ở trên sử dụng các biến thể hiện. Nếu bạn muốn sử dụng toán tử điều hướng an toàn với các biến cục bộ, bạn sẽ phải kiểm tra xem các biến cục bộ của bạn được xác định trước chưa.
# `user` local variable is not defined previous
user&.profile
# This code would throw the following error:
NameError: undefined local variable or method `user' for main:Object
Để khắc phục sự cố này, hãy kiểm tra xem biến cục bộ của bạn được xác định trước hay đặt thành 0:
# Option 1: Check the variable is defined
if defined?(user)
user&.profile
end
# Option 2: Define your local variable. Example, set it to nil
user = nil
user&.profile # Works and does not throw any errors
Rails có try
phương pháp về cơ bản là làm như vậy. Nó sử dụng send
phương thức bên trong để gọi một phương thức. Matz cho rằng nó chậm và đây phải là một tính năng ngôn ngữ tích hợp.
Nhiều ngôn ngữ lập trình khác có tính năng tương tự: Objective C, Swift, Python, Scala, CoffeeScript, v.v. Tuy nhiên, một cú pháp phổ biến là ?.
(dấu chấm câu). Nhưng, cú pháp này không thể được Ruby chấp nhận. Vì ?
được cho phép trong các tên phương thức và do đó, ?.
chuỗi ký hiệu đã là mã Ruby hợp lệ. Ví dụ:
2.even?.class # => TrueClass
Đó là lý do tại sao cộng đồng Ruby phải đưa ra các cú pháp khác nhau. Đó là một cuộc thảo luận tích cực và các tùy chọn khác nhau được coi là ( .?
, ?
, &&
, vv). Dưới đây là danh sách một số cân nhắc:
u.?profile.?thumbnails
u\profile\thumbnails
u!profile!thumbnails
u ? .profile ? .thumbnails
u && .profile && .thumbnails
# And finally
u&.profile&.thumbnails
Trong khi chọn cú pháp, các nhà phát triển đã xem xét các trường hợp cạnh khác nhau và cuộc thảo luận khá hữu ích để đi qua. Nếu bạn muốn xem qua tất cả các biến thể và sắc thái của nhà điều hành, vui lòng xem thảo luận giới thiệu tính năng này trên trình theo dõi vấn đề chính thức của Ruby.
.?
và các lựa chọn khác đã được xem xét, nhưng &.
đã được chọn! Vì vậy, chỉ &.
sẽ làm việc.
&.
và không .?
, xấu của tôi. Cập nhật câu trả lời của tôi. Cảm ơn cho những người đứng đầu lên!
user.?profile
nên user&.profile
(không thể tự chỉnh sửa vì đây chỉ là chỉnh sửa 1 ký tự!).
Hãy cảnh giác! Mặc dù toán tử điều hướng an toàn thuận tiện nhưng cũng có thể dễ dàng tự lừa mình thay đổi logic của bạn với nó. Tôi khuyên bạn nên tránh sử dụng nó trong kiểm soát dòng chảy. Thí dụ:
str = nil
puts "Hello" if str.nil? || str.empty?
# The above line is different than the below line
puts "Hello" if str&.empty?
Trong ví dụ đầu tiên, str.nil?
trả về true
và str.empty?
không bao giờ được gọi, khiến puts
câu lệnh được thực thi. Tuy nhiên, trong ví dụ thứ hai, str&.empty?
trả về nil
đó là falsey và puts
câu lệnh không bao giờ được thực thi.
str.nil?
là đúng (như bạn nói) có nghĩa là str.empty?
thực sự sẽ không được gọi (đó là cách thức ||
hoạt động của nhà điều hành). Phần còn lại của tuyên bố của bạn là chính xác.
puts "hello" unless str&.present?
(chỉ dành cho phương pháp hiện tại?)
nó được sử dụng để kiểm tra con số không, chẳng hạn như trong kotlin và swift Chẳng hạn; với Object -> Swift và Kotlin
model = car?.model
mô hình này có thể là con số không (Swift) hoặc null (Kotlin) nếu chúng ta chưa xác định giá trị mô hình trong lớp xe hơi. chúng tôi sử dụng ký hiệu đó thay vì dấu hỏi trong ruby
model = car&.model
nếu sử dụng car.model mà không có ký hiệu và nếu model không thì hệ thống không thể tiếp tục chạy.
try!
phương thức, không phảitry