2013-01-21 21 views
11

Tôi muốn làm điều nàyLàm thế nào để tạo ra một đối tượng người hoạt động như một False trong Ruby

lol = Klass.new(values) 

unless lol 
    print "false" 
end 

lol.other_method # it is not nil or false, it is a Klass instance! 

Nhưng lol, trong trường hợp này, không phải là con số không hay sai, nhưng một đối tượng người có thể đóng vai trò như A dựa sai trên một số giá trị nội bộ. Tôi có tùy chọn này

lol = Klass.new(values) 

unless lol.to_bool 
    print "false" 
end 

Nhưng IMHO xấu xí.

Tôi đã suy nghĩ mở rộng FalseClass hoặc chơi với == nhưng không thành công. Bất kỳ ý tưởng?

+0

Không rõ: giá trị 'Klass.method (giá trị)' là phương pháp 'Object #'? Nó lấy một tên phương thức làm đối số và trả về một phương thức mà sau này bạn có thể gọi 'call'. – user1852994

+0

thay vào đó, hãy tưởng tượng một "mới" hoặc một hàm tạo –

Trả lời

9

Thật không may, điều này là không thể.

Đây là một trong những trường hợp gây phiền nhiễu mà Ruby không hướng đối tượng. Trong OO, phải có thể cho một đối tượng mô phỏng một đối tượng khác (thực tế, tùy thuộc vào người bạn hỏi, đây là định nghĩa của OO - hãy nhớ rằng OO đã được mô phỏng), nhưng không thể xây dựng một đối tượng mô phỏng false. Điều này là bởi vì, trong Ruby, các cấu trúc điều khiển có điều kiện được đưa vào ngôn ngữ và không dịch thành tin nhắn gửi đi, trong khi đó các ngôn ngữ OO khác chỉ là thông điệp gửi thông thường (hoặc ít nhất dịch thành tin nhắn gửi đi, giống như for trong Ruby dịch thành each). Ví dụ, trong Smalltalk, Booleans đang thực sự thực hiện bằng cách sử dụng mã hóa Church of Booleans bạn biết từ Lambda Calculus, và dịch Ruby họ nhìn một chút như thế này:

class FalseClass 
    def if(&block) 
    # do nothing 
    end 

    def if_then_else(then_lambda, else_lambda) 
    else_lambda.() 
    end 

    def not 
    true 
    end 

    def and(&block) 
    self 
    end 

    def or(&block) 
    block.() 
    end 
end 

TrueClass chỉ là hình ảnh phản chiếu:

class TrueClass 
    def if(&block) 
    block.() 
    end 

    def if_then_else(then_lambda, else_lambda) 
    then_lambda.() 
    end 

    def not 
    false 
    end 

    def and(&block) 
    block.() 
    end 

    def or(&block) 
    self 
    end 
end 

Và sau đó, thay vì một cái gì đó giống như

if 2 < 3 then foo end 
if 2 < 3 then bar else baz end 

Bạn sẽ phải

(2 < 3).if { foo } 
(2 < 3).if_then_else(-> { bar }, -> { baz }) 

# using the new keyword arguments in Ruby 2.0, it almost reads like Smalltalk: 
class FalseClass 
    def if(then: -> {}, else: -> {}) 
    else.() 
    end 
end 

class TrueClass 
    def if(then: -> {}, else: -> {}) 
    then.() 
    end 
end 

(2 < 3).if(then: -> { bar }, else: { baz }) 

Bằng cách đó, bạn có thể dễ dàng tạo đối tượng mô phỏng false chỉ đơn giản bằng cách triển khai các phương pháp tương ứng.

Trong trường hợp khác, nơi một số đối tượng thực sự hoàn toàn phải là một phiên bản của một lớp cụ thể chứ không chỉ nói đúng giao thức, Ruby cung cấp một lối thoát hiểm. Ví dụ: nếu một phương thức thực sự là yêu cầu một đối số, thì trước tiên nó sẽ cố gắng gọi to_ary để ít nhất cho bạn cơ hội chuyển đổi đối tượng của mình thành một Array.Điều tương tự cũng xảy ra với to_str, to_int, to_proc, to_float v.v. Nhưng không có giao thức to_bool tương đương.

+0

Cảm ơn. Tôi đã cố gắng để làm điều này: https://github.com/peczenyj/Lazy-Bool - Tôi chọn Perl BTW. Tôi sẽ suy nghĩ về ví dụ của bạn và cố gắng làm một cái gì đó tương tự như em Ruby. –

4

Câu trả lời ngắn: Đừng làm điều này.

Câu trả lời dài là trong Ruby chỉ có chỉ hai thứ được đánh giá là sai: falsenil. Nghĩa đen tất cả mọi thứ khác đánh giá là đúng sự thật.

Nhiều ứng dụng phụ thuộc vào hành vi này và có thể sẽ không hoạt động nếu bạn bằng cách nào đó quản lý để thay đổi điều này. Nó giống như việc xác định 1 là một số chẵn. Nó sẽ gây ra vấn đề.

+0

trong trường hợp này, tùy chọn tốt nhất là thêm một .to_bool để đánh giá điều này trong ngữ cảnh boolean, phải không? –

+2

@TiagoPeczenyj 'một đối tượng có thể hoạt động như một giả dựa trên một số giá trị nội bộ' -> chỉ cần thêm một phương thức' false? 'Trả lời giá trị bên trong và sau đó' trừ khi lol.false? '. Nó không phải xấu xí, nhưng tốt bụng gõ vịt, nếu tôi không nhầm. – user1852994

+0

Việc thêm một phương thức 'sai?' Có vẻ hơi lạ một chút, đặc biệt khi xem xét 'false.false? 'Sẽ là một phương thức không xác định. – tadman

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