Xác định loại vật thể trong ruby


365

Tôi sẽ sử dụng python như một ví dụ về những gì tôi đang tìm kiếm (bạn có thể nghĩ nó là mã giả nếu bạn không biết Python):

>>> a = 1
>>> type(a)
<type 'int'>

Tôi biết trong ruby ​​tôi có thể làm:

1.9.3p194 :002 > 1.class
 => Fixnum 

Nhưng đây có phải là cách thích hợp để xác định loại đối tượng?


5
@ JörgWMittag Tuy nhiên, AFAICR là những gì `type` làm trong Python, mặc dù bộ nhớ của tôi mờ. Bạn sẽ cần isinstance hoặc kiểm tra phản hồi. Nhưng chỉ cần nói "NOES !!!" bây giờ không thực sự hữu ích phải không? Thay vào đó hãy xem xét việc giáo dục.
Dave Newton

4
@ JörgWMittag Trong khi tôi thông cảm, OP đã cung cấp mã để bắt chước trong Ruby. Trừ khi bạn thực sự giáo dục OP nói rằng noes không hữu ích, IMO. Và ngay cả khi bạn đã làm, nó chỉ có thể là thông tin, vì OP đã xác định những gì anh ấy muốn mã thông qua.
Dave Newton

5
@ JörgWMittag - trong Ruby mọi thứ đều là Object, vì vậy không có kiểu nguyên thủy như trong Python (int, long, boolean, v.v.) Kết quả là trong Ruby, các lớp là định nghĩa kiểu. Điều này cũng không giới hạn ở Ruby, lớp từ và loại đồng nghĩa với một số ngôn ngữ khác và rộng hơn là trong lý thuyết OOP.
ocodo

6
Vì chúng ta thực sự đang nói về Ruby ở đây, Các loại và Lớp là đồng nghĩa, không có tranh luận về điều này, tất cả các giá trị đều là Đối tượng. Vì vậy, đối với bất cứ ai chỉ đơn giản là nói về Ruby, Classes là các loại. - ref: ruby-lang.org/en/about
ocodo

2
@ JörgWMittag Bài tiểu luận đó khá nhiều thông tin cho đến nay và tôi sẽ đọc phần còn lại của nó khi tôi có cơ hội. Cụ thể, Cook dường như nói rõ khá rõ (và với kiến ​​thức nền tảng nhiều hơn tôi có) tại sao không đúng khi tuyên bố (như một trong những giáo sư của tôi đã làm) rằng Python, Ruby và các ngôn ngữ được gõ động khác "không thực sự phản đối định hướng "(điều mà anh ta có lẽ có nghĩa là, mà không nhận ra điều đó, là họ không định hướng ADT). Nhưng Ruby không được gõ tĩnh, do đó, nó không có ADT theo nghĩa mà Cook đang mô tả, vì vậy sự phản đối của bạn trên cơ sở sự khác biệt đó không hữu ích.
Kyle Strand

Câu trả lời:


608

Cách thích hợp để xác định "loại" của một đối tượng, đó là một thuật ngữ lung lay trong thế giới Ruby, là gọi object.class.

Vì các lớp có thể kế thừa từ các lớp khác, nếu bạn muốn xác định xem một đối tượng có "thuộc một loại cụ thể" hay không, bạn có thể gọi object.is_a?(ClassName)để xem nếu objectthuộc loại ClassNamehoặc xuất phát từ nó.

Thông thường việc kiểm tra kiểu không được thực hiện trong Ruby, nhưng thay vào đó, các đối tượng được đánh giá dựa trên khả năng đáp ứng các phương thức cụ thể của chúng, thường được gọi là " Gõ vịt ". Nói cách khác, nếu nó đáp ứng các phương thức bạn muốn, không có lý do gì để cụ thể về loại.

Ví dụ, object.is_a?(String)quá cứng nhắc vì một lớp khác có thể thực hiện các phương thức chuyển đổi nó thành một chuỗi hoặc làm cho nó hoạt động giống hệt như cách hành xử của Chuỗi. object.respond_to?(:to_s)sẽ là một cách tốt hơn để kiểm tra xem đối tượng trong câu hỏi có làm những gì bạn muốn không.


13
-1. #classkhông không trả về kiểu của đối tượng, nó sẽ trả về của nó lớp . Tên nên là một giveaway chết. Class và Type là hai khái niệm hoàn toàn khác nhau trong OO.
Jörg W Mittag

78
@ Jorg W Mittag: Tôi không đồng ý. "Lớp" và "tốc độ bộ xử lý" (để chọn một ví dụ) là hai khái niệm hoàn toàn khác nhau, nhưng "lớp" và "loại" là các khái niệm liên quan chặt chẽ với nhau. Ví dụ, đây là những gì bài viết Wikipedia trên Class nói: "Trong lập trình hướng đối tượng, một lớp là một cấu trúc được sử dụng để xác định một loại khác biệt." tadman là hữu ích cho người hỏi.
Teemu Leisti

18
@ JörgWMittag Trong Ruby điều gần gũi nhất với typeofC, JavaScript và những thứ khác là class. Không có hệ thống giao thức chính thức nào trong Ruby giống như ở các ngôn ngữ khác, Objective-C là nhóm Smalltalk gần nhất với điều đó. Nếu bạn đang xác định "loại" là "đối tượng đáp ứng với một nhóm phương thức cụ thể có kết quả chấp nhận được" thì thực sự không có cách nào để khẳng định điều đó. Nó quá lỏng lẻo. Hầu hết thời gian trong Ruby khi đề cập đến một loại đối tượng, nó hiểu rằng bạn đang nói về lớp. Tôi đã sử dụng loại thuật ngữ trong dấu ngoặc kép vì lý do đó.
tadman

14
@ Jorg W Mittag: Tôi tiếp tục khẳng định rằng "lớp" và "loại" chắc chắn không phải là những khái niệm hoàn toàn khác nhau trong OO, như được minh họa bằng trích dẫn. (Ngoài ra: làm thế nào để bạn khai báo một biến trong Java Bằng cách đưa ra? Hoặc các loại hoặc các lớp của biến, tiếp theo là tên gọi của nó: " int i" hoặc " Integer j".) Tadman đã trả lời các câu hỏi trong một cách mà dường như để thỏa mãn cả người chất vấn và đối tượng chung, đồng thời làm rõ thuật ngữ mà Ruby sử dụng. Tôi không có hứng thú với việc chia tóc hàn lâm về những điểm tốt hơn của thuật ngữ hướng đối tượng, vì vậy xin vui lòng có từ cuối cùng.
Teemu Leisti

11
@TeemuLeisti Hầu hết các rắc rối ở đây xuất phát từ thực tế là tất cả mọi thứ trong Ruby là một đối tượng, và do đó có một lớp, trong khi ở hầu hết các ngôn ngữ khác có nguyên thủy loại mà không phải là các đối tượng và không có lớp, trái ngược với đối tượng mà làm. Khi không có thứ gọi là loại thuần túy và không có cách nào để định nghĩa chính thức, thì ý nghĩa sẽ trở nên đặc biệt mơ hồ trong thế giới Ruby. Matz không tuân thủ nghiêm ngặt bất kỳ trường phái tư tưởng cụ thể nào ở đây ngoài trường phái của mình.
tadman

81

bạn cũng có thể thử: instance_of?

p 1.instance_of? Fixnum    #=> True
p "1".instance_of? String  #=> True
p [1,2].instance_of? Array #=> True

44

Thông thường trong Ruby, bạn không thực sự quan tâm lớp của đối tượng là gì, bạn chỉ quan tâm rằng nó đáp ứng với một phương thức nhất định. Cái này được gọi là Duck Typing và bạn sẽ thấy nó trong tất cả các loại cơ sở mã Ruby.

Vì vậy, trong nhiều trường hợp (nếu không phải hầu hết), tốt nhất nên sử dụng Duck Typing bằng cách sử dụng #respond_to?(method):

object.respond_to?(:to_i)

1
điểm hợp lệ. không trả lời câu hỏi nhưng đánh vào tinh thần của câu hỏi.
dùng566245

@ user566245 nó trả lời_to? (: the_question), nhưng như bạn nói nó không trả lời câu hỏi, chỉ cung cấp thông tin liên quan. Khá chắc chắn câu trả lời cần trả lời câu hỏi.
R. Rincón

17

Tôi sẽ nói có". Như "Matz" đã nói điều gì đó như thế này trong một trong những cuộc nói chuyện của anh ta, "các vật thể Ruby không có loại." Không phải tất cả mà là phần mà anh ấy đang cố gắng để vượt qua chúng tôi. Tại sao mọi người lại nói "Mọi thứ đều là Vật"? Để thêm, ông nói "Dữ liệu có loại không phải đối tượng".

Vì vậy, chúng tôi có thể tận hưởng điều này.

https://www.youtube.com/watch?v=1l3U1X3z0CE

Nhưng Ruby không quan tâm nhiều đến loại đối tượng chỉ là lớp. Chúng tôi sử dụng các lớp không phải loại. Tất cả dữ liệu sau đó có một lớp.

12345.class

'my string'.class

Họ cũng có thể có tổ tiên

Object.ancestors

Họ cũng có các lớp meta nhưng tôi sẽ tiết kiệm cho bạn các chi tiết về điều đó.

Khi bạn biết lớp rồi, bạn sẽ có thể tra cứu phương pháp nào bạn có thể sử dụng cho nó. Đó là nơi cần "kiểu dữ liệu". Nếu bạn thực sự muốn tìm hiểu chi tiết, hãy tìm kiếm ...

"Mô hình đối tượng Ruby"

Đây là thuật ngữ được sử dụng cho cách Ruby xử lý các đối tượng. Đó là tất cả nội bộ vì vậy bạn không thực sự thấy nhiều về điều này nhưng thật tuyệt khi biết. Nhưng đó là một chủ đề khác.

Đúng! Lớp là kiểu dữ liệu. Đối tượng có các lớp và dữ liệu có các loại. Vì vậy, nếu bạn biết về cơ sở dữ liệu thì bạn biết chỉ có một tập hợp các loại hữu hạn.

số khối văn bản


Chẳng hạn,Object.ancestors # => [Object, Kernel, BasicObject]
Dorian
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.