2012-06-24 37 views
10

Gần đây tôi đã gặp một số hành vi lạ với toán tử defined? được sử dụng để kiểm tra xem từ khóa super có thể được sử dụng trong ngữ cảnh hiện tại hay không. Thông thường nó hoạt động tốt, nhưng khi tôi cố gắng để kết hợp các kiểm tra defined? super với một chút nhỏ của metaprogramming, nó đã cho tôi kết quả bất ngờ.Hành vi lạ được xác định? (Siêu) kiểm tra

Nó dễ dàng hơn để hiển thị sau đó để mô tả, vì vậy đây là một ví dụ cất để minh họa cho vấn đề:

class A; 
    def self.def_f!; 
    singleton_class.send(:define_method, :f) { defined? super } 
    end 
end 
class AA < A; end 

(AAA lớp cả hai đều có .def_f! phương pháp lớp)

A.def_f! 

A.f # => nil 
AA.f # => nil 

(A.f không có siêu và AA.f gửi tới A.f, vì vậy mọi thứ vẫn ổn, nhưng ...)

AA.def_f! # define its own .f method in the AA class 

AA.f # => "super" 
A.f # => "super" # WHY??? 

Có ai có thể giải thích cho tôi dòng cuối cùng không? A.f không có phương thức siêu, vậy tại sao nó trả về "super" thay vì nil? Nó là một lỗi?

(Tôi đã thử nó trong 1.9.2 và 1.9.3-cùng kết quả)

UPD: Tôi mở một vé trên bugtracker Ruby: http://bugs.ruby-lang.org/issues/6644

+3

Sau khi xem các nguồn Ruby, tôi nghĩ bạn đã tìm thấy một lỗi thực sự ở đây. Bạn nên báo cáo nó với trình gỡ lỗi Ruby. –

+1

Và nếu bạn làm như vậy, đừng quên đăng liên kết tới vấn đề ở đây! ':)' –

+1

@NiklasB. Xong: http://bugs.ruby-lang.org/issues/6644 – Alexis

Trả lời

2

Ok, vì vậy @Niklas đã đúng, tôi đã báo cáo sự cố này với trình gỡ lỗi Ruby và họ đã xác nhận và sửa lỗi: https://bugs.ruby-lang.org/issues/6644.

Theo như tôi đã hiểu, bản sửa lỗi sẽ được đưa vào ruby ​​2.0.0.

+0

Cảm ơn bạn đã báo cáo và để theo dõi! –

1

Vâng có một vài quirks với define_method , đây không phải là vấn đề với defined?(super) thực sự, nhưng nhiều hơn với define_method. Có nói rằng, bất cứ khi nào tôi gặp phải một trường hợp cạnh như thế này với define_method, tôi thường chỉ kết thúc eval'ing một chuỗi mã Ruby và nó luôn luôn kết thúc làm việc như mong đợi.

module M; 
    def def_f! 
    singleton_class.class_eval <<-RUBY 
     def f 
     defined?(super) 
     end 
    RUBY 
    end 
end 

class A; extend M; end 
class AA < A; end 

A.def_f! 

p A.f # => nil 
p AA.f # => nil 

AA.def_f! # define its own .f method in the AA class 

p AA.f # => "super" 
p A.f # => nil 

Là tại sao nó hoạt động theo cách này, tôi không đủ kinh nghiệm với nguồn Ruby để biết, có thể ai đó biết nhiều hơn tôi làm thể chỉnh sửa. Nhưng đối với các mục đích thực tế, đánh giá một chuỗi đã luôn luôn làm việc cho tôi.

+0

Tôi vẫn tin rằng vấn đề là nhiều hơn với 'được xác định? (Siêu)', nhưng cảm ơn vì cách giải quyết. – Alexis