Làm cách nào để khởi tạo các biến phiên bản của mô-đun trong Ruby?


80

Tôi có một số mô-đun mà tôi muốn sử dụng các biến phiên bản. Tôi hiện đang khởi tạo chúng như sau:

module MyModule
  def self.method_a(param)
    @var ||= 0
    # other logic goes here
  end
end

Tôi cũng có thể gọi một phương thức init để khởi tạo chúng:

def init
  @var = 0
end

nhưng điều này có nghĩa là tôi phải nhớ luôn gọi nó.

Có cách nào tốt hơn để làm điều này không?


3
Không phải khối mã đầu tiên đặt var thể hiện mô-đun (một var trong phạm vi của đối tượng kiểu của MyModule), trong khi khối thứ hai đặt var thể hiện "thuần túy" (var trong phạm vi của một cá thể bao gồm mô-đun)? Tôi nghĩ rằng hai khối mã này không làm cùng một điều ...
Boris B.

Câu trả lời:


109

Khởi tạo chúng trong định nghĩa mô-đun.

module MyModule
  # self here is MyModule
  @species = "frog"
  @color = "red polka-dotted"
  @log = []

  def self.log(msg)
    # self here is still MyModule, so the instance variables are still available
    @log << msg
  end
  def self.show_log
    puts @log.map { |m| "A #@color #@species says #{m.inspect}" }
  end
end

MyModule.log "I like cheese."
MyModule.log "There's no mop!"
MyModule.show_log #=> A red polka-dotted frog says "I like cheese."
                  #   A red polka-dotted frog says "There's no mop!"

Điều này sẽ thiết lập các biến cá thể khi mô-đun được xác định. Hãy nhớ rằng, bạn có thể mở lại mô-đun sau để thêm các biến phiên bản và định nghĩa phương thức hoặc để xác định lại những biến hiện có:

# continued from above...
module MyModule
  @verb = "shouts"
  def self.show_log
    puts @log.map { |m| "A #@color #@species #@verb #{m.inspect}" }
  end
end
MyModule.log "What's going on?"
MyModule.show_log #=> A red polka-dotted frog shouts "I like cheese."
                  #   A red polka-dotted frog shouts "There's no mop!"
                  #   A red polka-dotted frog shouts "What's going on?"

12
Đó là một thời gian, nhưng yeah :). Thêm vào đó, tôi cảm thấy rằng tất cả những gì cần nói về Messrs Foo và Bar đã được nói ra.
rapter

Vì vậy, tại thời điểm này, không phải là các biến thể hiện, mà là các phương thức thể hiện?
nipponese

nipponese: những gì không phải là biến cá thể?
rapter

5

Bạn có thể dùng:

def init(var=0)
 @var = var
end

Và nó sẽ mặc định là 0 nếu bạn không vượt qua bất cứ điều gì.

Nếu bạn không muốn phải gọi nó mọi lúc, bạn có thể sử dụng một cái gì đó như sau:

module AppConfiguration
   mattr_accessor :google_api_key
   self.google_api_key = "123456789"
...

end

Vì vậy, tôi vẫn cần gọi chức năng này trước khi làm bất cứ điều gì với mô-đun?
Geo

Tôi đã thêm một cách thứ 2 để tránh vấn đề đó - đó là từ mã rails
Brian

2

cho một lớp, tôi sẽ nói như sau, vì khởi tạo được gọi bất cứ khi nào bạn .new một thể hiện mới của lớp.

def initialize
   @var = 0
end

từ Ruby thực tế :

Nó tiếp tục nói rằng khởi tạo của một mô-đun sẽ được gọi nếu khởi tạo của một lớp bao gồm gọi super, nhưng không đề cập rằng đây là hệ quả của cách super hoạt động ở mọi nơi, không phải xử lý đặc biệt để khởi tạo. (Tại sao người ta có thể cho rằng việc khởi tạo được xử lý đặc biệt? Bởi vì nó được xử lý đặc biệt liên quan đến khả năng hiển thị. Các trường hợp đặc biệt tạo ra sự nhầm lẫn.)


1
Vì nó là một mô-đun, mặc dù khởi tạo sẽ được gọi? Đó là câu trả lời đầu tiên của tôi. Tôi đã thêm thứ hai để giải thích cho nó không được gọi.
Brian

1
OP đặc biệt đề cập mô-đun, không lớp
Zensaburou

2

tôi đã trả lời một câu hỏi tương tự , bạn có thể đặt các biến phiên bản lớp làm việc này

module MyModule
  class << self; attr_accessor :var; end
end

MyModule.var
=> nil

MyModule.var = 'this is saved at @var'
=> "this is saved at @var"

MyModule.var    
=> "this is saved at @var"

2

Rõ ràng đó là hình thức không tốt để khởi tạo các biến cá thể trong một mô-đun trong Ruby. (Vì lý do tôi không hiểu đầy đủ, nhưng liên quan đến thứ tự mà mọi thứ được khởi tạo.)

Có vẻ như phương pháp hay nhất là sử dụng trình truy cập với khởi tạo lười biếng, như sau:

module MyModule
  def var
    @var ||= 0 
  end
end

Sau đó, sử dụng varnhư getter cho @var.


4
Lưu ý này sẽ không bao giờ cho phép bạn thiết lập @var đến nilhayfalse
thép
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.