Computer >> Máy Tính >  >> Lập trình >> Ruby

Mọi thứ bạn cần biết về các nhà khai thác Ruby

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à ||=&&= .

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ặc nil sau đó gán 100 cho nó, nếu không, chỉ cần trả về giá trị của a

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ính
attr_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ện
condition ? 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 🙂