2009-09-28 31 views
9

Mới đối với Ruby, và tôi đang cố gắng tìm ra thành ngữ nào để sử dụng để hạn chế một số giá trị số nguyên cho hàm tạo của một lớp.Ruby Constructors and Exceptions

Từ những gì tôi đã thực hiện cho đến nay, nếu tôi nêu ngoại lệ trong initialize(), đối tượng vẫn được tạo nhưng sẽ ở trạng thái không hợp lệ (ví dụ: một số giá trị nil trong các biến mẫu). Tôi không thể nhìn thấy cách tôi phải hạn chế các giá trị mà không đi vào những gì trông các bước lớn không cần thiết như hạn chế truy cập vào new().

Vì vậy, câu hỏi của tôi là, theo cơ chế nào tôi có thể hạn chế phạm vi giá trị mà đối tượng được khởi tạo?

+0

Yeah, tôi nhầm lẫn bản thân mình về vấn đề này. Tôi đã 'giải cứu' ngoại lệ trong constructor, vì vậy nó là lý do mà instance đó sẽ được tạo ra. – Chris

Trả lời

13

Huh, bạn hoàn toàn chính xác rằng đối tượng vẫn còn sống ngay cả khi initialize đặt ra một ngoại lệ. Tuy nhiên, nó sẽ là khá khó khăn cho bất cứ ai để treo vào một tham chiếu trừ khi bạn bị rò rỉ self ra khỏi initialize như đoạn mã sau tôi chỉ viết không:

>> class X 
>> def initialize 
>>  $me = self 
>>  raise 
>> end 
>> def stillHere! 
>>  puts "It lives!" 
>> end 
>> end 
=> nil 
>> t = X.new 
RuntimeError: 
    from (irb):14:in `initialize' 
    from (irb):20:in `new' 
    from (irb):20 
>> t 
=> nil 
>> $me 
=> #<X:0xb7ab0e70> 
>> $me.stillHere! 
It lives! 
3

Tôi không chắc chắn về tuyên bố này:

Từ những gì tôi đã làm cho đến nay, nếu tôi nâng một ngoại lệ trong initialize(), đối tượng vẫn tạo nhưng sẽ nằm trong trạng thái không hợp lệ (ví dụ: một số giá trị nil trong các biến mẫu).

class Foo 

    def initialize(num) 
    raise ArgumentError.new("Not valid number") if num > 1000 
    @num = num 
    end 

end 

f = Foo.new(4000) #=> n `initialize': not valid (RuntimeError) 
+0

Hmm, tôi sẽ phải xem lại mã của mình và xem có thể tôi đã nhầm. Cảm ơn câu trả lời. – Chris

+1

Trên thực tế, đối tượng * được tạo ra, nó chỉ là .new sẽ không trả lại tham chiếu, vì vậy trừ khi đối tượng liên kết với chính nó trong 'initialize', nó sẽ nhận được gc'ed. – DigitalRoss

2

Nếu tôi đọc câu hỏi của bạn một cách chính xác, những gì bạn muốn là một cái gì đó như thế này:

class SerialNumber 
    VALID_SERIAL_NUMBERS = (0..10,000,000,000) 
    def initialize(n) 
    raise ArgumentError.new("Serial numbers must be positive integers less than 10 Billion") unless VALID_SERIAL_NUMBERS.include?(n) 
    @n = n 
    end 
end 

Đừng lo lắng rằng SerialNumber.new tạo ra một thể hiện trước đó phương pháp được gọi là initialize - nó sẽ được dọn sạch nếu lỗi được nâng lên.

0

Sử dụng validatable module có vẻ như phù hợp thực sự trong ngữ cảnh.

Dưới đây là một ví dụ về cách sử dụng nó:

class Person 
    include Validatable 
    validates_numericality_of :age 
    end 

Đối với thực hiện một số chỉ trong một phạm vi cụ thể nó sẽ là:

class Person 
    include Validatable 
    validates_numericality_of :age 
    validates_true_for :age, :logic => lambda { (0..100).include?(age) } 
    end 

Điều này tất nhiên sẽ xác nhận độ tuổi đó là trong vòng phạm vi 0 và 100.