Ruby: kind_of? so với instance_of? so với is_a?


488

Sự khác biệt là gì? Khi nào nên sử dụng? Tại sao có rất nhiều trong số họ?


18
Về lý do cả hai is_a?kind_of?tồn tại: Tôi cho rằng đó là một phần trong triết lý thiết kế của Ruby. Python sẽ nói rằng chỉ nên có một cách để làm một cái gì đó; Ruby thường có các phương thức đồng nghĩa để bạn có thể sử dụng phương thức nghe hay hơn. Đó là một vấn đề ưu tiên. Một phần có thể là do ảnh hưởng của Nhật Bản: Tôi được cho biết rằng họ sẽ sử dụng một từ khác cho cùng một số tùy thuộc vào câu để làm cho âm thanh hay hơn. Matz có thể đã mang ý tưởng đó vào thiết kế ngôn ngữ của mình.
Nathan Long

@NathanLong Tôi không nghĩ quầy của Nhật Bản có liên quan nhiều đến nó; tất cả các ngôn ngữ đều có một số thỏa thuận và bạn không thể thay thế một bộ đếm trong một thời gian khác (như, bạn không thể sử dụng bộ đếm hình trụ cho các vật thể phẳng; nó chỉ sai). Và nó có liên quan nhiều đến ngữ nghĩa hơn là euphony.
Casey

Câu trả lời:


622

kind_of?is_a?đồng nghĩa.

instance_of?khác với hai cái còn lại ở chỗ nó chỉ trả về truenếu đối tượng là một thể hiện của lớp chính xác đó, không phải là lớp con.

Thí dụ:

  • "hello".is_a? Object"hello".kind_of? Objecttrả về true"hello"là một StringStringlà một lớp con của Object.
  • Tuy nhiên "hello".instance_of? Objecttrả lại false.

77
Nó chỉ đọc tốt hơn đôi khi. Hãy suy nghĩ @honda.kind_of? Car@person.is_a? Administrator, tất cả về thẩm mỹ của Ruby. Trên thực tế, hãy chú ý đến lỗi ngữ pháp ... với sự hỗ trợ tích cực mà bạn có thể viết @person.is_an? Administrator:) ... Điều đó có thể đã biến nó thành lõi Ruby ngay bây giờ, thực sự.
rfunduk

2
heh đó là một lý do thú vị bạn có thể phá vỡ điều này, bạn? như bạn có thể ghi đè kind_of?nhưng không is_a??
Claudiu

3
@thenduks, is_an?không có trong ruby-1.9.2-p0. @Claudiu, không. is_a?chỉ là một bí danh củakind_of? . Cả hai phương thức đều gọi hàm c giống nhau , rb_obj_is_kind_of.
ma11hew28

9
@Matt: Bạn có thể ghi đè một bí danh mà không ghi đè hàm bí danh. Vì vậy, có, bạn có thể ghi đè kind_of?mà không ghi đè is_a?.
sepp2k

4
is_an?Phương thức ActiceSupport này ở đâu?! Đây không phải là phiên bản đường ray hiện tại và tôi không thể tìm thấy bất cứ điều gì trên google về việc nó bị phản đối.
Tom Lord

22

Sự khác biệt là gì?

Từ tài liệu:

- ( Boolean )instance_of?(class)
Trả truenếu objlà một thể hiện của nhóm nhất định.

và:

- ( Boolean ) is_a?(class)
- ( Boolean )kind_of?(class)
Lợi nhuận truenếu classlà lớp obj, hoặc nếu classlà một trong những superclasses của objhoặc mô-đun bao gồm trong obj.

Nếu điều đó không rõ ràng, thật tốt khi biết chính xác những gì không rõ ràng, để tài liệu có thể được cải thiện.

Khi nào nên sử dụng?

Không bao giờ. Sử dụng đa hình thay thế.

Tại sao có rất nhiều trong số họ?

Tôi sẽ không gọi hai "nhiều". Có hai người trong số họ, vì họ làm hai việc khác nhau.


3
Tôi nghĩ rằng sự nhầm lẫn của tôi là có 3, và 2 chỉ làm điều tương tự và có tên khác nhau. Về việc sử dụng đa hình - Tôi đồng ý, nhưng thư viện tiêu chuẩn ruby ​​có đầy đủ các cách sử dụng của mỗi trong số đó
Claudiu

4
Bạn có ý nghĩa gì bởi đa hình? Có giống như gõ vịt không?
Andrew Grimm

2
Vâng, chúng giống nhau. Gõ vịt là một dạng đa hình.
SpaceGhost

3
Có thường là tốt hơn để làm đa hình, vâng, nhưng có những trường hợp đường viền mà bạn thực sự muốn biết rằng bạn có một lớp cụ thể, chẳng hạn như khi bạn đang xử lý các tệp.
Automatico

6

Nó giống như Ruby hơn khi hỏi các đối tượng xem họ có đáp ứng với một phương thức bạn cần hay không, bằng cách sử dụng respond_to?. Điều này cho phép cả giao diện tối thiểu và thực hiện lập trình không biết.

Tất nhiên không phải lúc nào cũng có thể áp dụng, do đó vẫn có khả năng hỏi về cách hiểu bảo thủ hơn về "loại", đó là lớp hoặc lớp cơ sở, sử dụng các phương thức bạn hỏi về.


5
Nó phụ thuộc vào tình hình. Cả Nhận xét và Blog có thể phản hồi với created_at. Trong tình huống như vậy là_a? thích hợp hơn IMHO
penkovsky

Điều đó không có ý nghĩa, nếu bạn cần thiết để phân biệt một Nhận xét và một đối tượng Blog từ mỗi khác, bạn chỉ đơn giản là sẽ không sử dụng created_at để làm điều đó. Điều đó không loại trừ rằng bạn có thể viết một phương thức lấy một đối tượng đáp ứng với created_at. Nếu nó không cần bất cứ điều gì khác để thực hiện công việc của mình, thì bạn có thể sử dụng nó một cách an toàn trên Comment hoặc Blog, hoặc bất kỳ mô hình ActiveRecord nào khác.
Kingdon

3

Tôi cũng sẽ không gọi hai nhiều ( is_a?kind_of?là bí danh của cùng một phương thức), nhưng nếu bạn muốn xem nhiều khả năng hơn, hãy chuyển sự chú ý của bạn sang #classphương thức:

A = Class.new
B = Class.new A

a, b = A.new, B.new
b.class < A # true - means that b.class is a subclass of A
a.class < B # false - means that a.class is not a subclass of A
# Another possibility: Use #ancestors
b.class.ancestors.include? A # true - means that b.class has A among its ancestors
a.class.ancestors.include? B # false - means that B is not an ancestor of a.class

1
Cảm ơn - tôi thực sự đã hỏi theo nghĩa chung về "thông tin loại thời gian chạy nào có thể được thu thập trong Ruby và bằng cách nào" - và điều này cung cấp các ví dụ phong phú
Claudiu
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.