2016-12-01 15 views
6

Trong Ruby, tra cứu liên tục bị ảnh hưởng bởi cách lồng và các phương thức giữ lại lồng nhau của chúng.Làm thế nào để tìm được cách lồng vào trong Ruby?

Ví dụ, nếu tôi có các phân hệ:

module A 
    X = 1 
end 

module B 
    X = 2 
end 

module Foo 
end 

tôi có thể xác định một phương pháp Foo.a mà có một tổ của [A, Foo]:

module Foo 
    module ::A 
    Module.nesting #=> [A, Foo] 
    def Foo.a 
     X 
    end 
    end 
end 

Foo.a #=> 1 

Và một phương pháp Foo.b mà có một tổ của [Foo, B] :

module B 
    module ::Foo 
    Module.nesting #=> [Foo, B] 
    def Foo.b 
     X 
    end 
    end 
end 

Foo.b #=> 2 

Sự khác biệt trở nên rõ ràng nếu tôi xác định Foo::X:

Foo::X = 3 

Foo.a #=> 1 <- still resolves to A::X 
Foo.b #=> 3 <- now resolves to Foo::X 

Nhưng làm cách nào để xác định lồng của một phương thức nhất định?

+0

Thành thật mà nói, tôi thậm chí không chắc chắn tại sao 'Foo.a' và' Foo.b' được xác định và có sẵn trong chính. –

+0

@EricDuminil Tôi muốn nói vì ':: Foo', nó đề cập đến hằng số cấp cao nhất. – Stefan

+0

Đã không nhận ra rằng các mô-đun cấp cao nhất có thể được lồng vào người khác, wow. – akuhn

Trả lời

4

này sẽ làm việc:

Foo.method(:a).to_proc.binding.eval('Module.nesting') 
#=> [A, Foo] 

Foo.method(:b).to_proc.binding.eval('Module.nesting') 
#=> [Foo, B] 

Tested với Ruby 2.2.1 và 2.3.1. Nó không hoạt động với Ruby 2.1.5.

+1

Có, nó giúp, cảm ơn! – Stefan

+0

Bạn nói _ "Tôi không thể kiểm tra nó trên điện thoại của tôi" _ - đây có phải là một dự đoán may mắn hay bạn biết rằng nó sẽ hoạt động? – Stefan

+2

Giả sử đó là một phỏng đoán được giáo dục, đã giúp với tài liệu chính thức của Ruby. –

2

Bạn đang suy nghĩ về nó một cách sai lầm. Không có điều nào như "lồng các phương thức". Các hằng số được lồng vào đâu đó. Nesting có độ phân giải đường dẫn được kết nối với tên của các mô-đun và các lớp. Các phương thức được chứa trong một mô-đun/lớp (có thể là "bình thường" hoặc singleton).


Trường hợp phương thức được đặt là ngữ nghĩa. Có một khái niệm, tương tự như self, xác định nơi một phương thức sẽ được định nghĩa, được gọi là định nghĩa mặc định. Không có từ khóa cho nó, nhưng nó tương đương với:

kind_of?(Module) ? name : self.class.name 

đâu một hằng số được đặt/tìm kiếm là hoàn toàn cú pháp. Khi bạn tham khảo X, nó không quan tâm chút ít nếu bạn đặt cho nó một phương pháp hay không:

DEEP_MIND = Object.new 

module Foo 
    X = 42 
end 

module Foo 
    module Bar 
    def DEEP_MIND.talk 
     p X 
    end 
    end 
end 

DEEP_MIND.talk # => 42 

module Foo::Bar 
    def DEEP_MIND.talk 
    p X 
    end 
end 

DEEP_MIND.talk # => uninitialized constant 

Tất cả phải quan tâm là những gì "làm tổ hiện tại" trên dòng của mã nơi bạn cố gắng tham khảo nó.


Bây giờ, nếu bạn thực sự muốn tìm "làm tổ hiện tại bên trong cơ thể của phương pháp", sau đó bạn cần một số cách để giả vờ bạn đang thực sự ở đó.

Đáng buồn thay, tôi không nghĩ có cách nào khác ngoài cách được hiển thị trong @Eric's answer. Sử dụng khối với instance_eval/instance_exec sẽ cung cấp cho bạn việc lồng vào vị trí khối đã được xác định.

+0

_ »Không có thứ gì như" lồng ghép các phương thức "« _ - nhưng để đánh giá một phương thức, Ruby phải biết làm tổ của nó. Trong ví dụ của tôi, 'Foo.b' đầu tiên giải quyết thành' B :: X' và sau đó là 'Foo :: X'. Nó không đơn giản giải quyết tĩnh đến ':: B :: X', nó tôn trọng sự lồng nhau tại điểm tạo của nó, tức là' [Foo, B] '. – Stefan

+0

@Stefan * "nhưng để đánh giá một phương pháp, Ruby phải biết làm tổ của nó" * - không thực sự. Nó chỉ cần biết đối tượng mà nó được gọi. Hằng số không được giải quyết bằng phương thức. Nó được giải quyết bởi ngữ cảnh hiện tại trong mã. Nó chỉ xảy ra khi các phương thức có cách thuận tiện để có được ngữ cảnh/đóng cửa hiện tại - '# binding'. Bất cứ nơi nào bạn đang có, phương pháp hay không, những gì hiện tại làm tổ có thể được truy cập thông qua 'Module.nesting'. Nó sử dụng ràng buộc hiện tại. 'binding.eval ('Module.nesting')' chỉ sử dụng một ràng buộc khác để giả vờ nó có một ngữ cảnh khác. – ndn

+0

@Stefan, ok, bạn có thể nói một phương thức biết nó là ràng buộc, và ràng buộc (bất cứ nơi nào bạn đang có, phương pháp hay không) biết làm tổ hiện tại. Trong ý nghĩa đó, một phương thức biết cách làm tổ hiện tại của nơi nó được định nghĩa. Nhưng đó chỉ là ngẫu nhiên, nó không phải là ý tưởng rằng các phương thức được lồng nhau tương tự như các hằng số. – ndn

Các vấn đề liên quan