Trong Ruby, làm cách nào để kiểm tra xem phương thức “foo = ()” đã được định nghĩa chưa?


81

Trong Ruby, tôi có thể định nghĩa một phương thức foo = (bar):

irb(main):001:0> def foo=(bar)
irb(main):002:1>   p "foo=#{bar}"
irb(main):003:1> end
=> nil

Bây giờ tôi muốn kiểm tra xem nó đã được xác định chưa,

irb(main):004:0> defined?(foo=)
SyntaxError: compile error
(irb):4: syntax error, unexpected ')'
 from (irb):4
 from :0

Cú pháp thích hợp để sử dụng ở đây là gì? Tôi giả sử phải có một cách để thoát khỏi "foo =" để nó được phân tích cú pháp và chuyển chính xác đến định nghĩa? nhà điều hành.

Câu trả lời:


131

Vấn đề là foo=phương pháp được thiết kế để sử dụng trong các bài tập. Bạn có thể sử dụng defined?theo cách sau để xem những gì đang xảy ra:

defined? self.foo=()
#=> nil
defined? self.foo = "bar"
#=> nil

def foo=(bar)
end

defined? self.foo=()
#=> "assignment"
defined? self.foo = "bar"
#=> "assignment"

So sánh với:

def foo
end

defined? foo
#=> "method"

Để kiểm tra xem foo=phương thức có được xác định hay không, bạn nên sử dụng respond_to?:

respond_to? :foo=
#=> false

def foo=(bar)
end

respond_to? :foo=
#=> true

Cảm ơn! Điều này giải quyết vấn đề của tôi. Tôi vẫn tò mò muốn biết liệu có cách nào để thoát khỏi foo = để nó có thể được cung cấp cho định nghĩa không? nhưng ít nhất bây giờ tôi có thể tiếp tục.
Alex Boisvert

1
Vấn đề ở đây là nó foo=luôn được sử dụng trong các bài tập, vì vậy Ruby sẽ trả về "assignment"nếu bạn kiểm tra defined? foo()(xem câu trả lời cập nhật).
molf

41

Bạn có thể kiểm tra xem một phương thức có tồn tại hay không bằng cách sử dụng respond_to?phương thức đó và bạn chuyển cho nó một ký hiệu, ví dụ: bar.respond_to?(:foo=)để xem liệu đối tượng barcó một phương thức hay không foo=. Nếu bạn muốn biết liệu các trường hợp của một lớp có phản hồi với một phương thức mà bạn có thể sử dụng method_defined?trên lớp (hoặc mô-đun) hay không, chẳng hạn Foo.method_defined?(:bar=).

defined?không phải là một phương thức, mà là một toán tử trả về một mô tả của toán hạng (hoặc nil nếu nó không được định nghĩa, đó là lý do tại sao nó có thể được sử dụng trong câu lệnh if). Toán hạng có thể là bất kỳ biểu thức nào, tức là một hằng số, một biến, một phép gán, một phương thức, một lời gọi phương thức, v.v. Lý do tại sao nó không hoạt động khi bạn làm defined?(foo=)là do dấu ngoặc đơn, hãy bỏ qua chúng và nó sẽ hoạt động nhiều hơn hoặc ít hơn như mong đợi. Điều đó đang được nói, defined?là một toán tử khá kỳ lạ và không ai sử dụng nó để kiểm tra sự tồn tại của các phương thức.


Nó là response_to ?, không response_to?
0x4a6f4672

3
Ah, chính tả của thư viện lõi Ruby ... respond_to?, start_with?, end_with?.
Theo

3
stackoverflow.com/questions/5280556/… có một lời giải thích hay về sự lựa chọn đằng sau cách đặt tên TL; DRyou.knock if you.respond_to?(:knock)
drawish
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.