Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Truyền rõ ràng so với ép buộc ngầm trong Ruby:Giải thích #to_s so với #to_str

Ép buộc kiểu là việc thay đổi kiểu của một đối tượng thành kiểu khác, cùng với giá trị của nó. Ví dụ:thay đổi Số nguyên thành Chuỗi bằng #to_s hoặc Float thành một số nguyên có #to_i . #to_str có lẽ ít được biết đến hơn và #to_int các phương thức mà một số đối tượng triển khai thoạt nhìn có vẻ giống nhau, nhưng có một số khác biệt.

Trong phiên bản này của học viện AppSignal, chúng ta sẽ đi sâu vào các kiểu ép buộc rõ ràng và ép buộc ngầm trong Ruby, đồng thời đề cập ngắn gọn về các tác nhân đánh máy. Chúng tôi sẽ đề cập đến sự khác biệt giữa cả hai phương pháp và thảo luận về cách sử dụng chúng.

Trước tiên, hãy xem cách chúng ta thường ép buộc các giá trị thành các loại khác nhau trong Ruby bằng các trình trợ giúp truyền rõ ràng.

Người trợ giúp truyền rõ ràng

Những người trợ giúp truyền phổ biến nhất là #to_s , #to_i , #to_a#to_h . Đây là những phương pháp đúc rõ ràng. Chúng giúp chúng ta dễ dàng chuyển đổi một giá trị từ loại này sang loại khác.

Những người trợ giúp rõ ràng đi kèm với một lời hứa rõ ràng. Bất cứ khi nào #to_s được gọi trên một đối tượng, nó sẽ luôn luôn trả về một chuỗi, ngay cả khi đối tượng không thực sự chuyển đổi thành chuỗi. Giống như chọn Michael Keaton vào vai Batman vậy. Bạn sẽ có được một người dơi, ngay cả khi một diễn viên hài không đặc biệt phù hợp với vai diễn này.

Ruby cung cấp các phương thức trợ giúp này trên hầu hết mọi đối tượng cơ bản trong thư viện chuẩn Ruby.

 

Các phương thức này, đặc biệt là #to_s , được triển khai trên hầu hết các loại cơ bản trong Ruby. Mặc dù quá trình truyền hầu như luôn trả về một giá trị nhưng kết quả có thể không như chúng ta mong đợi.

 

Gọi #to_s , #to_i , #to_a#to_h người trợ giúp buộc bất kỳ giá trị nào vào loại đã chọn. Chúng trả về một đại diện của loại mà nó bị ép buộc bất kể điều gì xảy ra với giá trị.

Các phương pháp cưỡng chế ngầm

Việc gọi các phương thức truyền kiểu trên các giá trị không hoạt động giống kiểu mà chúng ta đang truyền tới có thể gây ra lỗi hoặc mất dữ liệu. Ruby cũng cung cấp các phương thức ép buộc ngầm chỉ trả về một giá trị khi các đối tượng hoạt động giống như kiểu đó. Bằng cách này, chúng ta có thể chắc chắn rằng giá trị hoạt động giống như loại chúng ta muốn. Các phương pháp cưỡng chế ngầm này là #to_str , #to_int , #to_ary#to_hash .

Sự ép buộc ngầm cũng giống như chọn Leonard Nimoy vào bất kỳ vai nào ngoại trừ Spock. Chúng sẽ hoạt động nếu nhân vật đủ gần với Spock, nhưng sẽ thất bại nếu không. #to_str người trợ giúp cố gắng để chuyển đổi thành chuỗi nhưng sẽ tăng NoMethodError nếu đối tượng không triển khai phương thức và không thể bị ép buộc một cách ngầm định.

 

Chúng ta có thể thấy rằng Ruby bây giờ nghiêm ngặt hơn một chút trong những gì nó thực hiện và không ép buộc các loại được yêu cầu. Nếu cưỡng ép không được thì #to_* phương thức không được triển khai trên đối tượng và việc gọi nó sẽ gây ra NoMethodError .

Khi sử dụng các biện pháp cưỡng chế ngầm, ví dụ:#to_str , chúng ta yêu cầu hàm trả về một đối tượng String, chỉ khi kiểu ban đầu cũng hoạt động giống như một String. Vì lý do này, #to_str chỉ được triển khai trên Chuỗi trong Thư viện chuẩn Ruby.

Cách Ruby sử dụng sự ép buộc ngầm

Ngoài việc chính xác hơn về những gì chúng ta yêu cầu trong quá trình ép buộc, việc ép buộc ngầm còn có ích lợi gì nữa? Hóa ra Ruby sử dụng chính sự ép buộc ngầm trong một số tình huống. Ví dụ:khi kết hợp các đối tượng với + .

 

Ở đây, chúng ta thấy Ruby tăng TypeError vì nó không thể thực hiện chuyển đổi ngầm định từ Name gõ vào String .

Nếu chúng tôi triển khai #to_str trên lớp, Ruby biết cách ép Name gõ.

 

Điều tương tự cũng xảy ra với Mảng và #to_ary .

 

Nhưng #to_ary được sử dụng trong nhiều tình huống hơn. Chúng ta có thể sử dụng nó để cấu trúc một mảng thành các biến riêng biệt.

 

Nó cũng thực hiện chuyển đổi đối tượng thành các tham số khối.

 

Có nhiều tình huống hơn trong đó các phương pháp cưỡng chế ngầm được sử dụng, chẳng hạn như #to_hash với ** . Điều này ép giá trị thành hàm băm với #to_hash trước khi chuyển nó tới parse_options phương pháp.

 

Các loại thực thi

Ruby cũng cung cấp các phương thức ép buộc linh hoạt hơn khi loại đó thuộc loại không xác định và chúng tôi muốn đảm bảo rằng chúng tôi nhận được đúng loại. Có một cái cho mọi loại cơ bản (String(...) , Integer(...) , Float(...) , Array(...) , Hash(...) , v.v.).

 

String(...) phương pháp đầu tiên cố gắng gọi #to_str về giá trị và khi thất bại, nó sẽ gọi #to_s phương pháp. Không phải tất cả các đối tượng đều xác định #to_str phương pháp, do đó kiểm tra bằng cả sự ép buộc ngầm (#to_str ) và rõ ràng (#to_s ) các phương pháp truyền sẽ tăng khả năng chuyển đổi Chuỗi sẽ hoạt động và bạn sẽ nhận được giá trị mình muốn. Bằng cách gọi cưỡng chế ngầm trước tiên, chúng ta có nhiều khả năng nhận được kết quả có cùng giá trị nhưng thuộc loại cưỡng bức chứ không phải kiểu như "#<Object:0x00007f8e6d053a90>" .

 

Bạn chỉ nên triển khai các phương thức truyền ngầm cho các đối tượng hoạt động giống như loại bị ép buộc, ví dụ:#to_str cho lớp String của riêng bạn.

Ngoài việc cố gắng ép buộc ngầm lần đầu tiên, String(...) người trợ giúp cũng kiểm tra kiểu trả về. #to_str chỉ là một phương thức có thể trả về bất kỳ loại giá trị nào, thậm chí không phải là Chuỗi. Để đảm bảo chúng tôi nhận được giá trị thuộc loại được yêu cầu String(...) tăng TypeError nếu các loại không khớp.

 

Ở đây, chúng ta có thể thấy Ruby bỏ qua kết quả của #to_str bởi vì nó trả về nil , không thuộc loại Chuỗi. Thay vào đó, nó quay trở lại #to_s kết quả.

Nếu #to_s cũng trả về nil và do đó không đúng loại, String(...) sẽ tăng TypeError .

 

Mặc dù chúng có thể đáng tin cậy hơn trong việc thực thi ép buộc kiểu, nhưng hãy lưu ý rằng các phương thức trợ giúp truyền (String(...) , Integer(...) , v.v.) thường chậm hơn một chút vì chúng cần thực hiện nhiều kiểm tra hơn đối với giá trị đã cho.

Tóm lại

Khi bạn muốn đảm bảo rằng bạn đang xử lý đúng loại dữ liệu cho một đối tượng, ép buộc kiểu là một quy trình hữu ích. Trong bài đăng này, chúng tôi đã cập nhật kiến thức của mình về các trình trợ giúp truyền rõ ràng như #to_s , #to_i , #to_a#to_h . Chúng tôi cũng đã xem xét các trường hợp khi người trợ giúp ngầm như #to_str , #to_int , #to_ary#to_hash hữu ích và cách chúng được chính Ruby sử dụng.

Chúng tôi hy vọng bạn thấy tổng quan về ép buộc kiểu này hữu ích và cách bạn tìm thấy sự tương tự về việc định kiểu tác nhân. Như mọi khi, hãy cho chúng tôi biết nếu có chủ đề nào bạn muốn chúng tôi đề cập. Nếu bạn có bất kỳ câu hỏi hoặc nhận xét nào, vui lòng liên hệ với chúng tôi @AppSignal.

Truyền rõ ràng so với ép buộc ngầm trong Ruby:Giải thích #to_s so với #to_str

Tom de Bruijn