Ruby có rất nhiều toán tử thú vị.
Thích :
- Toán tử phi thuyền (
<=>
) - Toán tử gán mô-đun (
%=
) - Bộ ba bằng (
===
) toán tử - Lớn hơn (
>
) &nhỏ hơn (<
) - Không bằng (
!=
)
Những gì bạn có thể không nhận ra là nhiều toán tử trong số này thực sự là các phương thức Ruby .
Điều này có nghĩa là…
Bạn có thể ghi đè những gì chúng làm và sử dụng chúng để xác định hành vi tùy chỉnh trong các lớp của riêng bạn.
Ví dụ:bằng cách xác định ==
bạn có thể cho Ruby biết cách so sánh hai đối tượng của cùng một lớp.
Bây giờ :
Hãy xem qua một vài ví dụ để bạn có thể có một cái nhìn tổng quan chắc chắn về cách hoạt động của các toán tử Ruby này và cách sử dụng chúng trong mã của bạn.
Đây là một chủ đề quan trọng nếu bạn thực sự muốn hiểu về Ruby.
Nội dung
- 1 Toán tử logic Ruby
- 2 Toán tử Số học Ruby
- 3 Toán tử chỉ định (==, + =, || =)
- 4 Các nhà khai thác đơn lẻ là gì?
- 5 Toán tử Ruby Splat (Có ví dụ)
- 6 Toán tử Đối sánh (=~)
- 7 Toán tử bậc ba của Ruby (Toán tử Dấu hỏi)
- 8 Toán tử Xẻng / Đẩy (<<)
- 9 Toán tử ba bình đẳng (Nhiều hơn bình đẳng)
- 10 Nhà điều hành Điều hướng An toàn (&.)
- 11 Bảng ưu tiên của toán tử
- 12 Tóm tắt
- 12.1 Có liên quan
Các toán tử logic của Ruby
Đầu tiên, chúng ta sẽ xem xét các toán tử logic.
Bạn có thể sử dụng các toán tử này để giúp bạn so sánh hai đối tượng &đưa ra quyết định dựa trên kết quả.
Đây là bảng:
Toán tử | Mô tả |
---|---|
< | Ít hơn |
> | Lớn hơn |
> = | Lớn hơn hoặc bằng |
<= | Nhỏ hơn hoặc bằng |
== | Bằng |
! = | Không bằng |
<=> | Lớn hơn, Bằng hoặc Nhỏ hơn |
Tất cả các toán tử này là các phương thức và chúng trả về giá trị boolean , ngoại trừ toán tử tàu vũ trụ. Toán tử tàu vũ trụ trả về 1 (lớn hơn), 0 (bằng) hoặc -1 (nhỏ hơn).
Dưới đây là ví dụ về cách sử dụng >
nhà điều hành:
if orange.stock > 20 # ... end
Nếu bạn muốn sử dụng dấu bằng kép (==
) với các lớp của riêng bạn, bạn có thể thấy rằng nó không hoạt động lúc đầu…
Ví dụ :
class Fruit def initialize(name) @name = name end end orange1 = Fruit.new("orange") orange2 = Fruit.new("orange") orange1 == orange2 # false
Lý do cho điều này là việc triển khai mặc định của ==
là BasicObject # ==, sử dụng object_id
để tìm hiểu xem hai đối tượng có giống nhau hay không.
Bạn có thể sửa lỗi đó như sau:
class Fruit attr_reader :name def initialize(name) @name = name end def ==(other) name == other.name end end
Ở đây chúng ta đang nói ý nghĩa của việc hai loại trái cây giống nhau:
Chúng phải có cùng tên.
Toán tử số học Ruby
Tập hợp các toán tử tiếp theo là các toán tử số học.
Không có gì mới ở đây…
5 + 5 # 10 10 * 2 # 20 10 ** 2 # 100
Nhưng cũng giống như ==
toán tử, đây là các phương thức.
Điều này hữu ích vì bạn có thể xác định ý nghĩa của việc thêm hai đối tượng cùng nhau .
Vì vậy, nếu bạn có hai Order
, việc cộng chúng lại với nhau sẽ cho bạn tổng số tiền phải trả hoặc bạn nhận được một đơn đặt hàng mới là sự kết hợp của hai đơn đặt hàng này.
Bạn có thể xác định chính xác cách bạn muốn nó hoạt động bằng cách xác định +
phương pháp.
Một toán tử khác mà bạn có thể không quen thuộc là toán tử mô-đun .
Nó trông giống như dấu phần trăm (%
).
Và những gì nó làm là mang lại cho bạn phần còn lại của một bộ phận .
Ví dụ :
10 % 2 # 0
Toán tử modulo có nhiều cách sử dụng thực tế , chẳng hạn như tìm xem một số là chẵn hay lẻ, nếu một số chia hết cho một số khác, để đặt giới hạn cho một số, v.v.
Toán tử chỉ định (==, + =, || =)
Tiếp theo là các toán tử gán và không giống như tất cả các toán tử mà chúng ta đã thấy cho đến bây giờ, đây không phải là các phương thức.
Bạn có toán tử gán cơ bản:
a = 1
Nhưng bạn cũng có các toán tử gán kết hợp:
a += 5 # 6 a *= 2 # 12
Chúng tương đương với việc đọc giá trị hiện tại và sử dụng một trong các toán tử số học với nó, sau đó lưu kết quả. Bạn có thể thực hiện việc này với tất cả các toán tử số học, bao gồm toán tử modulo (%
).
Nhưng có hai toán tử gán hoạt động theo một cách khác!
Đây là ||=
và &&=
.
Chúng khác nhau vì chúng không tương đương nhau sang các phiên bản số học.
Cái gì a ||= 100
có phải là cái này không:
“Nếu
a
không tồn tại hoặc nếu nó làfalse
hoặcnil
sau đó gán100
cho nó, nếu không, chỉ cần trả về giá trị củaa
”
Gần nhất tôi có thể nhận được một biểu thức tương đương là sau:
(defined?(a) && a) ? a : a = 100
Điều này hữu ích nếu bạn muốn lưu kết quả của một số tính toán chậm hoặc yêu cầu API, một quá trình được gọi là "ghi nhớ".
Các nhà khai thác đơn lẻ là gì?
Cho đến nay, bạn chỉ thấy các toán tử hoạt động với 2 giá trị, nhưng cũng có toán tử chỉ hoạt động với một giá trị , chúng tôi gọi đây là "toán tử một ngôi".
Ví dụ :
+"abc"
Điều này tạo ra một bản sao có thể thay đổi của một chuỗi cố định.
Bạn có thể xác định các toán tử một ngôi của riêng mình (+
/ -
), nhưng bạn sẽ cần một số cú pháp đặc biệt.
Ví dụ :
class String def +@ frozen? ? self.dup : self end end str = "abc".freeze p (+str).frozen? # false
Tôi phải sử dụng dấu ngoặc đơn ở đây vì toán tử ưu tiên của toán tử một ngôi.
Bạn cũng có !!
, không phải là một phương thức:
!!123 # true !!nil # false
Điều này hữu ích vì nó sẽ biến bất kỳ giá trị nào thành boolean .
Sau đó, bạn có !
, giống nhau nhưng nó cung cấp cho bạn giá trị boolean ngược lại.
Ví dụ :
!true # false !!true # true !false # true
Toán tử Ruby Splat (Có ví dụ)
Toán tử biểu tượng (*
) rất thú vị vì nó làm được điều gì đó mà bạn không thể làm được nếu không có nó.
Giả sử bạn có một mảng như thế này:
attributes = [:title, :author, :category]
Và bạn muốn sử dụng mảng này với một phương thức nhận các đối số biến, như attr_reader
.
Sau đó, bạn có thể làm điều này:
Các thuộc tínhattr_reader *attributes
Toán tử biểu tượng chuyển đổi mảng thành một danh sách các phần tử của nó. Vì vậy, nó sẽ giống như loại bỏ mảng và thay thế nó bằng mọi thứ bên trong nó.
Nói cách khác, ví dụ cuối cùng dịch thành:
attr_reader :title, :author, :category
Đó là sức mạnh của toán tử biểu tượng 🙂
Toán tử đối sánh (=~)
Toán tử Ruby trông buồn cười này là gì (=~
) bằng dấu ngã?
Đó là toán tử phù hợp!
Nó cho phép bạn thực hiện tìm kiếm chỉ mục nhanh chóng bằng cách sử dụng một biểu thức chính quy.
Đây là một ví dụ:
"3oranges" =~ /[0-9]/ # 0
Thao tác này tìm kiếm các số & trả về chỉ mục bên trong chuỗi nơi tìm thấy kết quả khớp đầu tiên , nếu không, nó trả về nil.
Ngoài ra, bạn có !~
toán tử, là toán tử "KHÔNG khớp".
Ví dụ :
"abc" !~ /[0-9]/ # false
Bạn sẽ nhận được true
hoặc false
với điều này, không có chỉ mục, vì vậy hãy ghi nhớ điều đó.
Toán tử bậc ba của Ruby (Toán tử dấu hỏi)
Nếu bạn thích mã nhỏ gọn và ngắn gọn thì bạn sẽ thích toán tử bậc ba của Ruby.
Đó là một cách để viết câu lệnh if / else nhỏ gọn.
Có vẻ như thế này :
điều kiệncondition ? true : false
Đây là một ví dụ :
"".size == 0 ? "Empty string" : "Non-empty string"
Đây là cách nó hoạt động :
Phần đầu tiên của toán tử bậc ba xác định điều kiện ("".size == 0
).
Sau đó, bạn có một biểu tượng dấu chấm hỏi (?
).
Sau đó, bạn có giá trị trả về cho khi điều kiện này đúng .
Sau đó là dấu hai chấm (:
).
Và phần cuối cùng là giá trị trả về cho khi điều kiện này sai , đây sẽ là else
trong một biểu thức điều kiện đầy đủ.
Người vận hành Xẻng / Đẩy (<<)
Toán tử này (<<
) cũng là một phương thức, vì vậy nó thay đổi những gì nó thực hiện tùy thuộc vào đối tượng mà bạn đang làm việc với.
Ví dụ:với mảng, nó chỉ là bí danh cho push
phương pháp.
animals = [] animals << "cat"
Với các chuỗi, nó sẽ nối vào cuối:
"" << "cat"
Và với Integers
, nó sẽ thực hiện "dịch chuyển trái", xoay tất cả các bit sang trái.
2 << 1 # 4 2 << 2 # 8 2 << 3 # 16
Toán tử ba bình đẳng (Nhiều hơn bình đẳng)
Toán tử cuối cùng của chúng ta hôm nay sẽ là về toán tử ba dấu bằng (===
).
Đây cũng là một phương pháp và nó xuất hiện ngay cả ở những nơi mà bạn không ngờ tới.
Ví dụ, trong một câu lệnh viết hoa:
case "bacon" when String puts "It's a string!" when Integer puts "It's an integer" end
Ruby đang gọi ===
tại đây trên lớp.
Như thế này:
String === "bacon"
Điều này so sánh lớp hiện tại với lớp của đối tượng khác.
Vì vậy, điểm của toán tử này là xác định sự bình đẳng trong ngữ cảnh của một tuyên bố tình huống.
Toán tử Điều hướng An toàn (&.)
Bạn có thể muốn gọi một phương thức trên một đối tượng, nhưng đối tượng này có thể là nil
, điều này không tốt vì gọi một phương thức trên nil
thường dẫn đến lỗi.
Một giải pháp :
if user && user.active # ... end
Cách tốt hơn để làm điều này :
if user&.active # ... end
&.
này là toán tử điều hướng an toàn (được giới thiệu trong Ruby 2.3), chỉ gọi active
phương thức trên user
nếu nó không phải là nil
.
Rất hữu ích!
Bảng ưu tiên toán tử
Ruby đánh giá mã nguồn của bạn theo một danh sách các ưu tiên, như những gì xảy ra trong toán học với phép nhân và dấu ngoặc đơn.
Điều này có thể trở thành nguồn gốc của tất cả các loại lỗi nếu bạn không hiểu cách hoạt động của nó.
Đây là bảng, từ mức độ ưu tiên cao hơn đến thấp hơn :
Các nhà khai thác!, ~, unary + |
** |
một lần - |
*, /,% |
+, - |
<<,>> |
& |
|, ^ |
>,> =, <, <= |
<=>, ==, ===,! =, =~,! ~ |
&& |
|| |
?,: |
modifier-Rescue |
=, + =, - =, * =, / =,% = |
được định nghĩa? |
không |
hoặc và |
modifier-if, modifier-if, modifier-while, modifier-allow |
{} khối |
do ... khối kết thúc |
Với công cụ sửa đổi-something, nó có nghĩa là phiên bản một lớp của những từ khóa này.
Ví dụ :
puts "awesome" if blog_name == "rubyguides"
Dưới đây là một ví dụ mà mức độ ưu tiên của khối có thể làm bạn ngạc nhiên:
# Returns array with uppercase characters p ["a", "b", "c"].map { |character| character.upcase } # Returns Enumerator object p ["a", "b", "c"].map do |character| character.upcase end
Trong trường hợp đầu tiên, nó hoạt động như mong đợi, trong trường hợp thứ hai, khối có mức độ ưu tiên thấp hơn nên map
cho rằng không có khối nào và trả về một điều tra viên.
Tóm tắt
Bạn đã học về nhiều toán tử của Ruby, từ các toán tử số học, logic và thậm chí là các toán tử một ngôi ít người biết hơn.
Nhiều toán tử trong số này thực sự là các phương thức mà bạn có thể triển khai trong các lớp của riêng mình.
Hy vọng bạn thấy điều này hữu ích và thú vị!
Cảm ơn vì đã đọc 🙂