自定义.is_a?在Ruby中

问题描述:

是否可以在Ruby中创建自定义is_a?自定义.is_a?在Ruby中

我有一个字符串,可以是我需要检查和决定的UID或昵称。

UID:001ABC123(始于3数字和6个字母结尾)

昵称:john(可以是任何东西,但从来没有以数字开头)

我希望能够做到:

t = '001ABC123' 

if t.is_a? UID 
    ... 
end 

这可能吗?

+2

添加'is_a'全球的字符串是一个非常糟糕的主意。如果项目中的任何其他人决定也将“is_a”方法添加到字符串 - 你会得到一些有趣的错误。 –

有关红宝石的伟大之处之一是您可以重新开放任何课程。所以这样的一个实现可能是这样的:

class String 
    def is_a?(type) 
     return true if type == UID 
    end 
end 
+0

该解决方案返回'nil'作为''string'.is_a?(String)',它应该是'true',并且很可能会在第三方库中破坏某些东西 – Vasfed

不污染全球String - 利用改进:

class UID < String 
end 

module CustomStringIsA 
    refine String do 
    def is_a? what 
     if what == UID 
     self == '123' 
     else 
     super 
     end 
    end 
    end 
end 

puts '123'.is_a?(UID) # false 

using CustomStringIsA 
puts '123'.is_a?(Fixnum) # false 
puts '123'.is_a?(UID) # true 

但更好的使用===,这样你就可以使用case这样的:

class UID < String 
    def self.=== str 
    str === '123' 
    end 
end 

class UID2 < String 
    def self.=== str 
    str === '456' 
    end 
end 

case '456' 
when UID 
    puts 'uid' 
when UID2 
    puts 'uid2' 
else 
    puts 'else' 
end 

如果您正在寻找简洁的检查方式,为什么不使用正则表达式并使用=~运算符进行匹配。

这与使用自定义is_a?一样整洁,不需要搞乱String类。

例如:

UID = /^[[:digit:]]{3}[[:alnum:]]{6}$/ 

t = '001ABC123' 

if t =~ UID 
    #... 
end