我有来自游戏的文本日志(例如)两种类型的条目即。聊天和活动。在大多数情况下,它们非常相似,因此我定义了一个LogEntry类;
class LogEntry < Array
def initialize(str)
super str.split
end
def parse
LogEntry.parse self
end
def LogEntry.parse(entry)
# Processes the elements that are in any Entry
# Figure out whether it's a Chat entry or an Event entry
# Returns an object of type LogChat or LogEvent
end
end
LogChat和LogEvent都会扩展LogEntry并进行与其域相关的进一步处理。一切都按预期工作;
chat = LogEntry.new("some chat")
event = LogEntry.new("some event")
chat.parse.class # => LogChat
event.parse.class # => LogEvent
问题: 类方法LogEntry.parse本质上返回适当类的解析条目。在这种情况下,解析的条目是重要的一点。但我们可以将实例方法'解析'重命名为'what_type_should_i_be?'。我希望对象对该信息采取行动并且'self.become LogEntry.parse(self)'
现在,要解析一个条目,我必须这样做;
entry = entry.parse
我想进一步推动这一点,以便我得到相同的结果;
entry.parse
我已经尝试过显而易见的事了;
class LogEntry
def parse
self = LogEntry.parse(self)
end
end
然而我收到错误Can't change the value of self
。有谁知道我应该如何实现这个目标?
修改 我已经改变了我的例子,因为许多答案都集中在许多条目的迭代上。查克的回答优雅地表明这种情况不是问题。
如果这引起了任何人的兴趣,我偶然发现Evil Ruby让你干涉'self.class'。关于它的一篇很好的Orielly文章称为Ruby code that will swallow your soul!我正在研究它是否能提供任何答案。 (编辑:evil.rb名字很好!低级别的东西似乎'不适合稳定/长期分发。)
答案 0 :(得分:2)
我认为根本问题在于each
是错误的方法。要么parse
更改对象的内部状态而不是对象本身,要么使用map!
用新版本替换集合中的对象。
entries.map! {|entry| entry.parse}
将更新数组中的对象,并在其上调用parse
,因此没有理由在self
方法中对parse
进行奇怪的处理。
答案 1 :(得分:2)
如果你可以将功能划分到不同的模块中,你可以随意 mutate extend()
self
:
class LogEntry
...
def parse! # This mutates self!
case LogEntry.parse!
when :chat
self.extend MyApp::LogChat
when :event
self.extend MyApp::LogEvent
else
raise MyApp::Exception, "waaah"
end
end
end
当然,您不必在重复拨打case
的情况下执行笨拙的self.extend()
声明,但您明白了。
答案 2 :(得分:0)
对于初学者,您的评论说LogEntry.parse返回LogChat或LogEvent对象。所以你要求对象将自己改变为不同类型的对象。
它看起来像类方法和实例方法有点混淆 我猜一点,但你为什么不能这样做:
entries.each do |entry|
some_type_log = entry.parse
some_type_of_log.save!
end
编辑: 对不起,想澄清一些事情。由于您正在解析属于LogEntry的数据,并且您希望条目自行解析,因此无需传入任何参数。只需保持parse方法无参数。
如果你知道什么类型的日志是什么,你可以跳过一个步骤并在途中解析它。 chat_entry = LogChat.new(:log =&gt; LogEntry)
然后创建一个名为log的方法,这是一个明确处理聊天相关项目的解析器。
答案 3 :(得分:0)
你在这里遇到了一些字符串/数组/ LogEntry混淆,但假设你得到了解决方案,最后你仍然希望有一个Array子类替换它自己的内容,你需要使用replace
:
self.replace(LogEntry.parse(self))