2010-05-20 32 views
32

Trong Ruby, làm cách nào để tạo một hằng số lớp riêng tư? (nghĩa là một trong đó là có thể nhìn thấy bên trong lớp nhưng không phải bên ngoài)Làm cách nào để tạo các hằng số lớp riêng trong Ruby

class Person 
    SECRET='xxx' # How to make class private?? 

    def show_secret 
    puts "Secret: #{SECRET}" 
    end 
end 

Person.new.show_secret 
puts Person::SECRET # I'd like this to fail 
+1

Tất nhiên, "private" trong Ruby không có nghĩa là ý nghĩa của nó trong hầu hết các ngôn ngữ . Ruby không phải là lớn trên ẩn, vì vậy nếu bạn muốn truy cập một cái gì đó, bạn luôn có thể (nhưng có lẽ không phải với cú pháp rõ ràng nhất). "Riêng tư" của Ruby chỉ nói rằng nó không thể đứng trước dấu chấm ('.') (mà tôi đoán cũng là một gợi ý tại sao nó sẽ không hoạt động trên' :: ') – Amadan

+2

Chỉ trong trường hợp. Ruby 1.9.3 hiện có các hằng số riêng tư. – whitequark

Trả lời

12

Bạn cũng có thể thay đổi thường xuyên của bạn vào phương thức lớp học:

def self.secret 
    'xxx' 
end 

private_class_method :secret 

Điều này làm cho nó có thể truy cập trong mọi trường hợp của lớp học, nhưng không phải bên ngoài.

+0

Có lẽ một chương trình meta nhỏ sẽ làm cho điều này trở nên ngon miệng hơn. – DMisener

+0

Tôi nghĩ về nó lâu hơn một chút và sau đó nhận ra cách tiếp cận trên không làm cho hằng số có sẵn cho các phương pháp ví dụ vì vậy tôi nghĩ rằng tôi sẽ gắn bó với @ @ var phương pháp tiếp cận. – DMisener

+0

@DMisener: Ruby có một phương pháp để thiếu các hằng số, nếu có ai muốn có ma thuật lập trình meta. –

9

Thay vì một hằng số mà bạn có thể sử dụng một @@ class_variable, mà luôn luôn là tư nhân.

class Person 
    @@secret='xxx' # How to make class private?? 

    def show_secret 
    puts "Secret: #{@@secret}" 
    end 
end 
Person.new.show_secret 
puts Person::@@secret 
# doesn't work 
puts Person.class_variable_get(:@@secret) 
# This does work, but there's always a way to circumvent privateness in ruby 

Tất nhiên sau đó ruby ​​sẽ không phải làm gì để thực thi các constantness của @@ bí mật, nhưng ruby ​​làm rất ít để thực thi constantness để bắt đầu với, vì vậy ...

+0

Cảm ơn ... Có vẻ hiển nhiên trong sự nhận thức. – DMisener

1

Vâng ...

@@secret = 'xxx'.freeze 

loại công trình.

131

Bắt đầu từ ngày ruby ​​1.9.3, bạn có phương pháp Module#private_constant, mà có vẻ là chính xác những gì bạn muốn:

class Person 
    SECRET='xxx'.freeze 
    private_constant :SECRET 

    def show_secret 
    puts "Secret: #{SECRET}" 
    end 
end 

Person.new.show_secret 
# => "Secret: xxx" 

puts Person::SECRET 
# NameError: private constant Person::SECRET referenced 
+5

Đây là câu trả lời đúng, IMHO. –

+1

Điều này thật tuyệt vời. Tôi không biết đây là chuyện gì cả. –

+0

Tôi không thấy phương thức này trong API 'Module' cho đến http://www.ruby-doc.org/core-2.0.0/Module.html (http://www.ruby-doc.org/core -1.9.3/Module.html) –

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