Cách kiểm tra xem một đối tượng Ruby có phải là Boolean hay không


122

Tôi dường như không thể kiểm tra một đối tượng có phải là boolean một cách dễ dàng hay không. Có cái gì như thế này trong Ruby không?

true.is_a?(Boolean)
false.is_a?(Boolean)

Ngay bây giờ tôi đang làm việc này và muốn rút ngắn nó:

some_var = rand(1) == 1 ? true : false
(some_var.is_a?(TrueClass) || some_var.is_a?(FalseClass))

Câu trả lời:


136

Cách đơn giản nhất mà tôi có thể nghĩ ra:

# checking whether foo is a boolean
!!foo == foo

6
lớp X; phản đối !; tự end end; x = X.new; !! x == x # => true
Alexey

5
Vâng, đó được gọi là kiểu gõ vịt và một nguyên tắc cốt lõi của OOP. Tôi nghĩ đó là một tính năng.
Konstantin Haase

62
Ngắn không có nghĩa là đơn giản. Ý tôi là, wtf là?
Grant Birchmeier

11
Biến foo thành boolean, kiểm tra xem nó có giống foo không.
Konstantin Haase

9
Lưu ý rằng phủ định kép được một số người chơi cờ (như RuboCop ) coi là kiểu xấu .
sschuberth

104

Tôi thấy điều này ngắn gọn và tự ghi lại:

[true, false].include? foo

Nếu sử dụng Rails hoặc ActiveSupport, bạn thậm chí có thể thực hiện truy vấn trực tiếp bằng in?

foo.in? [true, false]

Kiểm tra tất cả các giá trị có thể có không phải là điều tôi khuyên bạn nên áp dụng cho float, nhưng khả thi khi chỉ có hai giá trị khả thi!


1
câu trả lời hay nhất cho đến nay, mặc dù tôi cũng thích foo == true or foo == falseai đó đưa ra nhận xét.
Ryan Taylor

3
Tôi thích điều này vì nó ít khó hiểu hơn trong mục đích !!foo == foo.
stringn88keys

Con trăn! Chắc chắn là câu trả lời có ngữ nghĩa nhất ở đây cho đến nay.
JM Janzen

85

Không có Booleanlớp nào trong Ruby, cách duy nhất để kiểm tra là làm những gì bạn đang làm (so sánh đối tượng với truefalsehoặc lớp của đối tượng chống lại TrueClassFalseClass). Tuy nhiên, không thể nghĩ ra tại sao bạn lại cần chức năng này, bạn có thể giải thích không? :)

Tuy nhiên, nếu bạn thực sự cần chức năng này, bạn có thể hack nó trong:

module Boolean; end
class TrueClass; include Boolean; end
class FalseClass; include Boolean; end

true.is_a?(Boolean) #=> true
false.is_a?(Boolean) #=> true

1
cố gắng thực hiện đánh máy dựa trên giá trị hiện tại.
Lance Pollard

75
'Tại sao bạn lại làm điều đó?' (và các dẫn xuất) chỉ là một trong những câu hỏi khó chịu nhất là một kỹ sư có thể thực hiện một :)
vemv

11
1 bởi vì tôi có thể sử dụng trong rspec như:expect(some_method?(data)).to be_a(Boolean)
Automatico

3
Trường hợp khác khi cần phải kiểm tra loại, là khi bạn thực hiện chuyển đổi cơ sở dữ liệu và cần quấn dây với "quotes"nhưng không số và boolean
Daniel Garmoshka

23

Như đã nêu ở trên, không có lớp boolean chỉ TrueClass và FalseClass tuy nhiên bạn có thể sử dụng bất kỳ đối tượng nào làm chủ thể của if / trừ khi và mọi thứ đều đúng ngoại trừ các trường hợp của FalseClass và nil

Kiểm tra Boolean trả về một phiên bản của FalseClass hoặc TrueClass

(1 > 0).class #TrueClass

Monkeypatch to Object sau đây sẽ cho bạn biết liệu thứ gì đó là một phiên bản của TrueClass hay FalseClass

class Object
  def boolean?
    self.is_a?(TrueClass) || self.is_a?(FalseClass) 
  end
end

Chạy một số thử nghiệm với irb cho kết quả sau

?> "String".boolean?
=> false
>> 1.boolean?
=> false
>> Time.now.boolean?
=> false
>> nil.boolean?
=> false
>> true.boolean?
=> true
>> false.boolean?
=> true
>> (1 ==1).boolean?
=> true
>> (1 ==2).boolean?
=> true

4
Đơn giản hơn chỉ để viết self == true or self == false. Đó là những trường hợp duy nhất của TrueClass và FalseClass.
Chuck

@chuck trả lại kết quả tương tự ngoại trừ Time.now.boolean? trả về nil. Bất kỳ ý tưởng tại sao?
Steve Weet

Việc xác định kiểm tra lớp đối với bản thân trong phương thức này hơi không phù hợp. Bạn nên xác định hai phiên bản boolean, một cho TrueClass / FalseClass và một cho Object.
Konstantin Haase

4
Nguyên nhân là do một lỗi trong phiên bản Time#==Ruby 1.8 khiến so sánh với các giá trị không phải Thời gian trả về nil chứ không phải false.
Chuck

17

Nếu mã của bạn có thể được viết một cách hợp lý dưới dạng một câu lệnh tình huống, thì điều này khá ổn:

case mybool
when TrueClass, FalseClass
  puts "It's a bool!"
else
  puts "It's something else!"
end

6

Một đối tượng là boolean sẽ có một lớp TrueClass hoặc FalseClass vì vậy một lớp lót sau sẽ thực hiện thủ thuật

mybool = true
mybool.class == TrueClass || mybool.class == FalseClass
=> true

Phần sau cũng sẽ cung cấp cho bạn kết quả kiểm tra kiểu boolean đúng / sai

mybool = true    
[TrueClass, FalseClass].include?(mybool.class)
=> true

4

Vì vậy, hãy thử này (x == true) ^ (x == false)lưu ý bạn cần dấu ngoặc đơn nhưng cái này đẹp và nhỏ gọn hơn.

Nó thậm chí vượt qua gợi ý như "cuak" nhưng không phải là "cuak" ... class X; def !; self end end ; x = X.new; (x == true) ^ (x == false)

Lưu ý : Hãy thấy rằng điều này rất cơ bản nên bạn cũng có thể sử dụng nó trong các ngôn ngữ khác, điều đó không cung cấp "thứ là boolean".

Lưu ý 2 : Ngoài ra, bạn có thể sử dụng điều này để nói điều này là một trong số ??:"red", "green", "blue"nếu bạnadd more XORS... hoặc nói điều này là một trong số ??:4, 5, 8, 35.


Tại sao XOR? Tại sao không HOẶC?
Nakilon


0

Không. Không giống như bạn có mã của mình. Không có bất kỳ lớp nào tên là Boolean. Bây giờ với tất cả các câu trả lời bạn có, bạn sẽ có thể tạo một câu trả lời và sử dụng nó. Bạn có biết cách tạo lớp không? Tôi chỉ đến đây vì tôi chỉ đang tự hỏi ý tưởng này. Nhiều người có thể nói "Tại sao? Bạn phải biết cách Ruby sử dụng Boolean". Đó là lý do tại sao bạn nhận được câu trả lời mà bạn đã làm. Vì vậy, cảm ơn cho câu hỏi. Thức ăn cho suy nghĩ. Tại sao Ruby không có lớp Boolean?

NameError: uninitialized constant Boolean

Hãy nhớ rằng Đối tượng không có kiểu. Chúng là các lớp học. Đối tượng có dữ liệu. Vì vậy, đó là lý do tại sao khi bạn nói kiểu dữ liệu, nó có một chút nhầm lẫn.

Ngoài ra, hãy thử rand 2 vì rand 1 dường như luôn cho 0. rand 2 sẽ cho 1 hoặc 0 nhấp chuột chạy một vài lần ở đây. https://repl.it/IOPx/7

Mặc dù tôi không biết làm thế nào để tự tạo một lớp Boolean. Tôi đã thử nghiệm với nó nhưng ...

class Boolean < TrueClass
  self
end

true.is_a?(Boolean) # => false
false.is_a?(Boolean) # => false

Ít nhất chúng ta có lớp đó bây giờ nhưng ai biết cách lấy các giá trị phù hợ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.