天鹅、大虾和梭鱼--ruby的动态派发

#《天鹅、大虾和梭鱼》是小学二年级课文里的一则寓言故事,是写天鹅、大虾和梭鱼一起拉车,但是天鹅要往云裏钻,大虾弓著要往後走,梭鱼一心想往水裏跳,大家的劲儿没有往一处使,导致车子分毫未动
#我们的实现。这是一辆神奇的多人驾驶的汽车,开车时需要所有的司机一起使劲拉。
class Shrimp
	def go_back(driver_index)
		puts "#{driver_index}号司机大虾弓著要往後走"
	end
end

class Pike
	def go_swim(driver_index)
		puts "#{driver_index}号司机梭鱼一心想往水裏跳"
	end
end

class Swan
	def go_fly(driver_index)
		puts "#{driver_index}号司机天鹅要往云裏钻"
	end
end

class Car
	def initialize(*driver)
		@add_driver=Array(driver)
		puts "现在车上有#{@add_driver.length}位司机:#{@add_driver.to_s}"
	end

	def run
		@add_driver.each_with_index do |driver,index|
			if driver.is_a?(Shrimp)
				driver.go_back(index)
			elsif driver.is_a?(Pike)
				driver.go_swim(index)
			elsif driver.is_a?(Swan)
				driver.go_fly(index)
			end
		end
		puts "车子分毫未动"
	end
end

Car.new(Pike.new,Swan.new,Shrimp.new).run

#现在车上有3位司机:[#<Pike:0x007fa653890d18>, #<Swan:0x007fa653890cf0>, #<Shrimp:0x007fa653890cc8>]
#0号司机梭鱼一心想往水裏跳
#1号司机天鹅要往云裏钻
#2号司机大虾弓著要往後走
#车子分毫未动



这世界已经很混乱了,但是如果我们再添加一个司机 比如
class Me
	def go_make_trouble(driver_index)
		puts "#{driver_index}号司机:我是专门来捣乱的"
	end	
end


我们将不得不改写Car#run...以适应新司机的驾驶风格,但是事实上也许我们可以更简单的做到这一点
使用send,约定开我们的车,司机只需要会一个技能:go_*

class Me
	
end

class Car
	def new_run
		@add_driver.each_with_index do |driver,index|
			if method=driver.public_methods.grep(/go\_/).first
				driver.send(method,index)
			else
				puts "#{index}号司机#{driver.class.name}是个南郭先生,没有合格的SSS级驾照"
			end
		end
		puts "车子分毫未动"
	end
end

Car.new(Pike.new,Swan.new,Shrimp.new,Me.new).new_run

#现在车上有4位司机:[#<Pike:0x007fa653890778>, #<Swan:0x007fa653890750>, #<Shrimp:0x007fa653890728>, #<Me:0x007fa6538906d8>]
#0号司机梭鱼一心想往水裏跳
#1号司机天鹅要往云裏钻
#2号司机大虾弓著要往後走
#3号司机是个南郭先生,没有合格的SSS级驾照

#车子分毫未动



可能我们并不事先知道每位司机不同的驾驶风格,事实上这也不是一辆车应该关心的事情,对于一辆多人驾驶的车来说。通知每位司机开车就尽到义务了
记住:当你调用一个方法时 ,实际上是给一个对象发送了一个消息



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值