最簡單的改變來解決你的代碼是像這樣:
class Parser
def initialize(msg_id)
@my_methods = { 1 => method(:method_1), 2 => method(:method_2), 3 => method(:method_3) }
@my_methods[msg_id].()
end
def method_1; end
def method_2; end
def method_3; end
end
即,使用Object#method
方法獲取Method
對象,並使用Method#call
方法執行它。
但是,我們可以做出一些改進。首先,你的Hash
將Integer
與值相關聯。但有一個更好的數據結構已經這樣做了:Array
。 (注意:如果您的留言ID不按順序分配,那麼Hash
可能是正確的選擇,但是從你的例子的外觀上來看,他們只是Integer
期從1
計數。)
其次,硬編碼的方法在Parser#initialize
方法裏面可能不是一個好主意。應該有對協議的說明性描述,即消息ID及其對應的方法名稱。
class Parser
# this will make your message IDs start at 0, though
PROTOCOL_MAPPING = [:method_1, :method_2, :method_3].freeze
def initialize(msg_id)
@my_methods = PROTOCOL_MAPPING.map(&method(:method))
@my_methods[msg_id].()
end
def method_1; end
def method_2; end
def method_3; end
end
另一種可能是這樣的:
class Parser
PROTOCOL_MAPPING = []
private_class_method def self.parser(name)
PROTOCOL_MAPPING << name
end
def initialize(msg_id)
@my_methods = PROTOCOL_MAPPING.map(&method(:method))
@my_methods[msg_id].()
end
parser def method_1; end
parser def method_2; end
parser def method_3; end
end
或者,也許這樣的:
class Parser
PROTOCOL_MAPPING = {}
private_class_method def self.parser(msg_id, name)
PROTOCOL_MAPPING[msg_id] = name
end
def initialize(msg_id)
@my_methods = PROTOCOL_MAPPING.map {|msg_id, name| [msg_id, method(name)] }.to_h.freeze
@my_methods[msg_id].()
end
parser 1, def method_1; end
parser 2, def method_2; end
parser 3, def method_3; end
end
的'self.method(:method_1)'語法應該有工作就好了,但,只有'self'真的有'method_1'方法時,調用'method'方法時定義。例如,你可以在'initialize'方法中做到這一點,因爲這也是一個實例方法,'self'是你的Parser類的一個實例,但是如果你嘗試在類方法中做,它不會起作用,因爲'method_1'不是一個類方法。 – philomory