我正在通过一个关于"高级课程方法的在线代码训练营教程"当我发现奇怪的事情。首先定义 Person 类,特别是 #normalize_names 方法。基本上,此方法会遍历 @@ all 中存储的 Person 类的每个实例,并将存储在 person.name 中的名字和姓氏大写
class Person
attr_accessor :name
@@all = []
def self.all
@@all
end
def initialize(name)
@name = name
@@all << self
end
def self.normalize_names
self.all.each do |person|
person.name = person.name.split(" ").collect{|w| w.capitalize}.join(" ")
end
end
end
然后教程解释说&#34;鉴于人名的复杂程度是多么复杂,我们实际上应该将[方法]封装到 Person 实例中。&#34;因此,随后 #normalize_names 方法被重构为如此。
def normalize_name
self.name.split(" ").collect{|w| w.capitalize}.join(" ")
end
def self.normalize_names
self.all.each do |person|
person.name = person.normalize_name
end
end
因此&#34;简化了对所有人的全局数据起作用的类方法,并将实际规范化委托给原始实例。这是全球集团运营商的常见模式。&#34;这为什么常见?规范化名称的复杂性如何优于这种设计模式?
答案 0 :(得分:1)
缺少第一个normalize_names
实现的明显之处是,只更新一个人的方法?一个选项是编写另一个类方法,该方法接受单个人实例。为了分离关注点,可以将其分为两种方法:
def self.normalize_names
# note that 'self' can be omitted in most cases
all.each { |person| normalize_name person }
end
def self.normalize_name(person)
# note use of proc shorthand to shorten collect { |x| x.capitalize }
person.name = person.name.split(" ").collect(&:capitalize).join(" ")
end
现在至少有一种方法可以更新一个人(如果需要的话)。虽然没有确定的要求使用实例与类的方法,但可能需要稍微简洁的API,例如, person.normalize_name
而非Person.normalize_name(person)
。说实话,这可能是将其转移到实例方法的最大原因:
def self.normalize_names
all.each &:normalize_name
end
def normalize_name
# note that attr_writers ("self.name =") are one of the few places you need
# "self", to differentiate it from variable assignment
self.name = name.split(" ").map(&:capitalize).join " "
end