Looking to write a Tag class
I'm looking to write a Tag class (a tag is a string with no spaces). My first thought is to inher开发者_如何学Pythonit from String:
class Tag < String
def initialize(str)
raise ArgumentError if str =~ /\s/
super
end
end
Does this look correct? Are there any other methods I should redefine?
Are other letters ok?
you might want to ensure the string matches your criteria instead of not matching it.
Examples:
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.
Usage in class:
class Tag < String
def initialize(str)
raise ArgumentError unless str =~ /^[a-z]+$/
super
end
end
All that said, this sounds a lot like Ruby symbols.
You shouldn't inherit from String, both for reasons of good object-oriented design and pure pragmatism.
If you inherit from String, you are violating the Liskov Substitution Principle, which states that instances of subclasses should be substitutable for instances of their superclass. This is not the case here: I can insert a space in the middle of a String, but I can not insert a space in the middle of a Tag, therefore a Tag is not a substitue for a String, and thus shouldn't be a subclass.
And as a purely practical matter: you are inheriting roughly 100 public instance methods from String. Do you really want to audit (and potentially override) every single one of them to ensure they don't violate Tag's contract?
I would rather do something like this:
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
It will be quite a challenge to make it air tight. Currently:
puts Tag.new("with_space").tr!("_"," ") # ==> prints "with space"
You would basically need to specialize all mutating methods (like #tr!), calling super and adding a check at the end, and all methods returning a modified copy of self too (like #tr).
加载中,请稍侯......
精彩评论