Bạn đang làm việc với một số nguyên nhưng bạn muốn sử dụng các phương thức chuỗi (như gsub
) thay vào đó.
Bạn có thể làm gì?
Chuyển nó thành một chuỗi (với to_s
) sau đó chuyển đổi nó trở lại thành số nguyên (với to_i
).
Ví dụ :
Bạn có thể chuyển đổi Integer
1 đến String
“1”.
Sau đó, bạn có thể sử dụng các phương thức từ lớp mới, giúp bạn làm điều gì đó mà trước đây bạn không thể thực hiện được.
Hãy nhớ điều đó trong Ruby…
Mọi đối tượng đều được liên kết với một lớp và mọi lớp đều có một bộ phương thức cụ thể.
Trong bài viết này, bạn sẽ tìm hiểu về :
- Những phương thức chuyển đổi nào có sẵn trong Ruby
- Sự khác biệt giữa chúng là gì!
- Cách chọn đúng trong các tình huống khác nhau
Hãy làm điều này!
Phương pháp chuyển đổi ngắn (to_s, to_i)
Có thể bạn đã quen thuộc với nhóm phương pháp chuyển đổi đầu tiên này.
Các phương pháp như :
- to_i
- to_s
- to_a
Các phương thức này trả về một đối tượng mới của một lớp cụ thể đại diện cho đối tượng hiện tại.
Ví dụ :
(1..10).to_a # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Điều này nói lên :
“Tôi muốn chuyển đổi
Range
1..10 thành mộtArray
đại diện cho phạm vi đó. ”
Có nhiều cách mà Ruby gọi các phương thức chuyển đổi này cho bạn một cách ngầm định.
Giống như trong nội suy chuỗi:
"#{1}"
Điều này gọi 1.to_s
cho bạn, ngay cả khi bạn không nhìn thấy nó.
Bạn có thể tự kiểm tra bằng mã này :
module Log def to_s puts "to_s called" super end end class Integer prepend Log end puts "#{1}" # "to_s called"
Lưu ý :Bạn phải sử dụng
Fixnum
thay vìInteger
nếu bạn đang sử dụng Ruby 2.3 trở lên. Hoặc tốt hơn, hãy cập nhật phiên bản Ruby của bạn 🙂
Những phương pháp này khá dễ dãi và chúng không được cho là có ngoại lệ.
Ví dụ :
"aaaaaa".to_i # 0
0
này có thể làm bạn ngạc nhiên.
Nhưng đó là những gì bạn nhận được khi gọi to_i
trên một chuỗi không có số nguyên trên đó.
Như bạn sẽ thấy ở phần sau của bài viết này có một phiên bản nghiêm ngặt hơn của phương pháp này .
Phương thức chuyển đổi dài (to_str, to_int)
Bây giờ:
Nếu chúng ta có các phương thức chuyển đổi ngắn đó, tại sao chúng ta cần các phương thức như to_str
hoặc to_int
?
Sự khác biệt là gì?
Sự khác biệt nằm ở mục đích của họ.
Mọi lớp Ruby (ngoại trừ BasicObject
) triển khai to_s
để trả về chính nó dưới dạng một số kiểu biểu diễn chuỗi.
Nhưng chỉ vì một lớp trả về một chuỗi không có nghĩa là nó hoạt động như một chuỗi!
Hãy xem một ví dụ :
"" + 1 # TypeError: no implicit conversion of Fixnum into String
Hãy nghĩ về điều này :
Một chuỗi rỗng cộng với số nguyên sẽ trả về cái gì?
Tôi không biết.
Bạn có thể nói “1” (một chuỗi có số một).
Nhưng tại sao?
Đó không phải là điều mà hầu hết mọi người mong đợi trong trường hợp này.
Sẽ không hợp lý nếu thêm chúng… đó là lý do tại sao chúng tôi nhận được TypeError
này .
Và ngay cả khi điều đó được cho phép.
Còn điều này thì sao :
"" + {}
Đó là một chuỗi rỗng cộng với một hàm băm trống.
Cũng không có ý nghĩa!
Vì vậy, Ruby thay vì kiểm tra xem đối tượng khác có phải là một chuỗi hay không, điều này sẽ không tốt cho Đa hình, nó sẽ kiểm tra xem đối tượng đó có HÀNH ĐỘNG giống như một chuỗi hay không.
Đó là nơi to_str
phương pháp đi kèm.
Các lớp duy nhất triển khai to_str trong Ruby 2.5 :
-
String
-
NameError::message
-
Warning::buffer
Cách triển khai các phương pháp chuyển đổi của riêng bạn
Bạn có thể triển khai to_str
trên bất kỳ lớp nào.
Sau đó, bạn sẽ có thể sử dụng nó như một chuỗi.
Đây là một ví dụ :
class Cat def to_str "meow" end end "" + Cat.new # "meow"
Nhưng trừ khi lớp của bạn tương đương với một chuỗi, bạn không nên làm điều này .
Sử dụng to_s
thay vào đó.
Btw, điều này không chỉ dành cho +
phương pháp.
Nó cũng được sử dụng ở những nơi khác mà chỉ một đối tượng dạng chuỗi mới có ý nghĩa.
Thích :
[1,2,3].join(",")
Các phương thức chuyển đổi dài khác như to_int
&to_hash
theo cùng một logic.
Đó là lý do tại sao chúng tôi có những phương pháp khác nhau này.
Cách sử dụng trình bao bọc chuyển đổi
Nếu bạn chưa có đủ phương pháp chuyển đổi… đừng lo lắng vì tôi có một số phương pháp khác dành cho bạn!
Tôi muốn gọi những thứ này là “Trình bao bọc chuyển đổi”.
Họ là :
- Mảng ()
- Số nguyên ()
- Băm []
Đó là một số phương pháp trông khác thường ngay tại đó!
Lưu ý dấu ngoặc đơn &dấu ngoặc vuông…
… Đó là thứ duy nhất tách các phương thức này khỏi tên lớp của chúng.
Mục đích của những điều này là gì?
Array () sẽ chuyển BẤT KỲ ĐIỀU GÌ thành một mảng.
Dưới đây là một số ví dụ dành cho bạn :
Array(nil) # [] Array([]) # [] Array(1) # [1] Array("") # [""]
Đây là loại logic gì ???
Chà, phương pháp này tuân theo một bộ quy tắc rất cụ thể :
- Nếu đối tượng phản hồi với
to_ary
hoặcto_a
nó sẽ gọi đó và trả về giá trị - Nếu không, nó sẽ đặt đối tượng bên trong một mảng trống và trả về nó
Điều đó giải thích hành vi được hiển thị ở trên.
Điều này rất hữu ích nếu bạn đang viết một phương thức yêu cầu một mảng nhưng nó có thể nhận được bất kỳ thứ gì khác và làm cho phương thức của bạn gặp sự cố toàn bộ ứng dụng. Bạn có thể đảm bảo đó là một mảng bằng cách chuyển nó vào Array()
đầu tiên để tránh điều đó.
Bây giờ Integer()
.
Nó có một số quy tắc đặc biệt :
- Nếu đối tượng là một chuỗi và nội dung của chuỗi hoàn toàn tuân theo một biểu diễn số hợp lệ trong Ruby thì phương thức này sẽ trả về một Số nguyên. Tăng
ArgumentError
nếu định dạng không hợp lệ. - Nếu đối tượng không phải là một chuỗi, nó sẽ cố gắng gọi
to_int
, rồi đếnto_i
. - Nó sẽ tạo ra một
TypeError
nếu đối tượng không thể được chuyển đổi thành mộtInteger
hợp lệ sử dụng phương pháp chuyển đổi.
Ví dụ :
Integer(1) # 1 Integer("25") # 25 Integer("abc123") # ArgumentError (invalid value for Integer(): "abc123") Integer([]) # TypeError (can't convert Array into Integer)
Integer()
này phương pháp này hữu ích nếu bạn muốn đảm bảo 100% rằng bạn đang làm việc với Integer
hợp lệ .
Bây giờ Hash[]
.
Bạn có thể chuyển một mảng phần tử chẵn để nhận một hàm băm mới:
Hash[[["a", 1], ["b", 2], ["c", 3]]] # {"a"=>1, "b"=>2, "c"=>3}
Hữu ích nếu bạn đang xây dựng hàm băm của mình bằng cách hợp nhất các phần tử của hai mảng hoặc sử dụng một phương pháp như bản đồ.
Tóm tắt
Bạn đã tìm hiểu về các phương thức chuyển đổi khác nhau trong Ruby, tại sao chúng tồn tại và cách sử dụng chúng!
Tôi hy vọng bạn thấy điều này hữu ích 🙂
Nếu bạn thích bài viết này, bạn cũng sẽ thích cuốn sách của tôi, Ruby Deep Dive, hãy xem nó.