2009-11-24 26 views
17

Xét đoạn mã sau:phương pháp sơ thẩm trong module

module ModName 
    def aux 
    puts 'aux' 
    end 
end 

Nếu chúng ta thay thế module với class, chúng ta có thể làm như sau:

ModName.new.aux 

Modules không thể instanced, mặc dù. Có cách nào để gọi phương thức aux trên mô-đun không?

+3

cho một sử dụng ném đi, bạn có thể làm 'Object.new.extend (ModeName) .aux' – AJcodez

Trả lời

22

Hãy nghĩ về những gì aux là. Đối tượng nào sẽ phản hồi với aux? Đó là một phương thức cá thể, có nghĩa là các cá thể của các lớp bao gồm ModName sẽ trả lời nó. Mô-đun ModName chính nó không phải là một thể hiện của một lớp như vậy. Điều này cũng sẽ không hoạt động nếu bạn đã định nghĩa ModName là một lớp - bạn không thể gọi một phương thức cá thể mà không có một cá thể.

Mô-đun rất giống các lớp học có thể được trộn vào các lớp khác để thêm hành vi. Khi một lớp kết hợp trong một mô-đun, tất cả các phương thức thể hiện của mô-đun sẽ trở thành các phương thức thể hiện của lớp. Đó là một cách để thực hiện nhiều thừa kế.

Chúng cũng đóng vai trò thay thế cho không gian tên, vì mỗi mô-đun xác định không gian tên. Nhưng đó là phần không liên quan. (Ngẫu nhiên, các lớp học cũng có không gian tên riêng của chúng, nhưng làm cho nó thành một lớp hàm ý rằng bạn sẽ tạo ra các trường hợp của nó, vì vậy chúng sai về mặt khái niệm cho mục đích đó.)

+2

Một trường hợp sử dụng thực tế cho điều này là với phương pháp 'helper' của Sinatra lấy một mô-đun và trộn nó thành các yêu cầu. Nếu các phương thức mô-đun của bạn không dựa vào trạng thái (ví dụ: một hàm định dạng một chuỗi được truyền vào nó), chúng cũng có thể được gọi là bên ngoài thích hợp là 'MyHelperModule.foo (bar)'. Sử dụng 'module_function' (theo câu trả lời của @ JPabloFernández bên dưới) cho phép một phương thức 'cá thể' mô-đun đơn lẻ được truy cập dưới dạng các yêu cầu OP. – Phrogz

5

định nghĩa mô-đun đánh giá là 'đây là ...', tại sao?

Trong Ruby, mọi thứ đều là biểu thức, không có báo cáo hoặc khai báo. Điều đó có nghĩa là mọi thứ sẽ đánh giá một giá trị. Ví dụ: phương pháp puts luôn đánh giá là nil, giống như biểu thức định nghĩa phương thức def (ngoại trừ trong Rubinius, trong đó biểu thức def đánh giá là CompiledMethod đối tượng cho phương thức được xác định).)

Vì vậy, nếu mọi thứ được đánh giá thành giá trị, biểu thức định nghĩa mô-đun sẽ đánh giá là gì? Vâng, có một vài ứng cử viên: nó có thể đánh giá là nil, giống như biểu thức định nghĩa phương thức. Hoặc nó có thể tự đánh giá đối tượng mô-đun, sau khi tất cả, điều này những gì chúng tôi đang xác định, phải không? Nhưng trên thực tế, Matz đã chọn một tùy chọn thứ ba: các biểu thức định nghĩa mô-đun (và lớp) thực sự đánh giá bất kỳ biểu thức cuối cùng nào bên trong thân xác định mô-đun được đánh giá. (Điều này cho phép bạn dễ dàng mô phỏng hai khả năng khác bằng cách chỉ cần đặt nil hoặc self làm biểu thức cuối cùng bên trong thân xác định mô-đun.)

Trong trường hợp của bạn, biểu thức cuối cùng bên trong thân xác định mô-đun là một nhiệm vụ. Nhưng, một bài tập? Cái quái gì rằng trả lại? Đó không phải là một tuyên bố sao? Không, không phải trong Ruby. Mọi thứ là một biểu thức, và các bài tập không là ngoại lệ: biểu thức gán đánh giá bất kỳ thứ gì bên tay phải đánh giá. Ở đây, phía bên tay phải của biểu thức gán là một chuỗi ký tự, để đánh giá đối tượng chuỗi.

Vì vậy, toàn bộ biểu thức định nghĩa mô đun sẽ đánh giá thành chuỗi 'this is a const in module'.

+0

cảm ơn bạn Jörg W Mittag, đã hiểu. – freenight

+6

Câu hỏi được chỉnh sửa rất nhiều từ câu trả lời của Joerg, nếu có ai hơi bối rối về những gì anh ta đang nói đến. –

0
class Foo 
    include ModName 
end 
Foo.new.aux 
# output: aux 
19

Bạn có thể làm theo cách này:

module ModName 
    def aux 
    puts 'aux' 
    end 
    module_function :aux 
end 

và sau đó chỉ cần gọi nó là:

ModName.aux 
+4

Ngoài ra: nếu bạn đang sử dụng mô-đun * độc quyền * làm không gian tên, 'mở rộng tự' là một tùy chọn rõ ràng hơn để xác định mỗi và mọi phương thức như một module_function. – yaauie

+1

@yaauie Nếu bạn không chuyển đối số tới 'module_funciton', thì bất kỳ hàm nào bên dưới nó sẽ được tạo thành một hàm mô-đun. Nó hoạt động giống như 'private'. – LandonSchropp

14

Bạn cũng có thể nói

module ModName 
    extend self 

    def aux 
    puts 'aux' 
    end 
end 

Sau đó, bạn có thể bao gồm module bình thường, nhưng cũng gọi phương thức thông qua ModName.

2

Và nhiều hơn một chút ...

module Y 
    def Y.a 
    puts "a" 
    end 

    def Y.b 
    c 
    end 

    def self.c 
    puts "b -- c" 
    end 
end 

cuộc gọi (không có '.new'):

Y.a #=> "a" 
Y.b #=> "b -- c" 
Y.C#=> "b -- c" 
+1

'Y.c' cũng hoạt động. Bạn cũng có thể làm 'module Y; lớp << tự; def c; đặt "b - c"; kết thúc; kết thúc; 'và xác định' :: c' trên eigenclass của nó. –

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