我正在寻找一个Tag类(标签是一个没有空格的字符串)。我的第一个想法是从String继承:
class Tag < String
def initialize(str)
raise ArgumentError if str =~ /\s/
super
end
end
这看起来是否正确?还有其他方法我应该重新定义吗?
答案 0 :(得分:2)
其他信件还好吗?
您可能希望确保字符串符合您的条件,而不是不匹配它。
1. /^\w+$/ ensures at least one word character (ThisIsAValidTag_123)
2. /^[a-z]+$/ ensures at least one lowercase a to z only
3. /^[a-z]+$/i ensures at least one a to z upper *or* lowercase.
class Tag < String
def initialize(str)
raise ArgumentError unless str =~ /^[a-z]+$/
super
end
end
所有这一切,听起来很像Ruby symbols
。
答案 1 :(得分:2)
由于良好的面向对象设计和纯粹的实用主义,你不应该继承String
。
如果从String
继承,则违反了Liskov替换原则,该原则规定子类的实例应该可替代其超类的实例。这不是这种情况:我可以在String
的中间插入一个空格,但我无法在Tag
的中间插入空格,因此Tag
不是String
的替代,因此不应该是子类。
作为一个纯粹实际的问题:你从String
继承了大约100个公共实例方法。您确实想要审核(并可能覆盖)每一个以确保它们不违反Tag
合同吗?
我宁愿做这样的事情:
require 'facets/multiton'
class Tag
include Multiton
attr_reader :name
attr_accessor :description
private
def initialize name, description=nil
raise ArgumentError, 'Tag name cannot contain whitespace' if str =~ /\s/
self.name = name.to_s.dup.freeze
self.description = description unless description.nil?
end
attr_writer :name
def self.multiton_id name, description=nil
return name.to_s.downcase
end
end
答案 2 :(得分:1)
使气密性变得非常困难。目前:
puts Tag.new("with_space").tr!("_"," ") # ==> prints "with space"
你基本上需要专门化所有变异方法(如#tr!
),调用super并在最后添加一个检查,所有方法也返回self的修改后的副本(如#tr
)。