期待写一个Tag类

时间:2010-04-13 03:22:07

标签: ruby class tags

我正在寻找一个Tag类(标签是一个没有空格的字符串)。我的第一个想法是从String继承:

class Tag < String
  def initialize(str)
    raise ArgumentError if str =~ /\s/
    super
  end
end

这看起来是否正确?还有其他方法我应该重新定义吗?

3 个答案:

答案 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)。