如果我有一个小猫类别,我想要这个小猫类别有飞行功能,你会怎麽做?
直接写一个有飞行功能的小鸟类别,然後再叫小猫类别去继承它?
直接把飞行功能写在小猫类别里?
「继承」的概念是:
我只要让小猫类别去继承小鸟类别就好啦,反正小鸟会飞,所以继承之後的小猫就会飞了!
但第 1 种做法的设计有点怪怪的,好好的猫不当,为什麽要去当鸟?为了想要有飞行功能就去当别人家的小孩。第 2 种做法看来似乎可行,但如果之後又有「我希望我的这个小狗类别也会飞!」的需求,那这样又得在小狗类别里写一段飞行功能,飞行功能的程序码没办法共用。
这时候,模组就可以派上用场了。
飞行模组
在 Ruby 定义模组,使用的是 module 这个关键字:
module Flyable
def fly
puts "I can fly!"
end
end
写起来的手感跟类别一样,连模组名字的规定也跟类别一样,必须是常数(也就是大字英文字母开头)。模组定义好了之後,如果要把它拿来用,只要用 include 这个方法:
class Cat
include Flyable
end
kitty = Cat.new
kitty.fly # => I can fly!
把这个飞行模组挂上去,然後小猫就会飞了!之後如果小狗类别也想要有飞行功能的话,只要这样一行:
class Dog
include Flyable
end
小狗也会飞了。
类别跟模组写起来好像?
如果你注意到,在写类别或模组的时候,除了一个是用 class,另一个是用 module,其它几乎没什麽差别。事实上,在 Ruby 里,「类别」的上层类别就是「模组」,开 IRB 实验一下:
$ irb
>> Class.superclass
=> Module
既然类别跟模组之间是继承关系,让我们来看看这两个类别之间的差别:
$ irb
>> Class.instance_methods - Module.instance_methods
=> [:new, :allocate, :superclass]
可以发现身为「後代」的 Class 类别,比 Module 类别多了 3 个方法,就是因为 Module 类别少了这 3 个方法,所以它跟 Class 最大的差别,就是:
模组没办法 new 一个新的实体出来。
模组没办法继承别的模组。
除此之外,模组跟类别在本质上没什麽太大的差别。
要用继承还是要用模组?
如果你发现你要做的这个功能,它可能在很多不同体系的类别里都会用得到,那你可以考虑把功能写在模组里,需要的时候再 include 进来即可。但如果你还是不知道到底类别跟模组有什麽差别,我再举二个例子。
不知道大家有没看过火影忍者这部漫画,漫画里的主人公之一,宇智波佐助,因为他们家族血统的关系,他写轮眼这个功能是天生就有的,你可以想像他这个功能算是从他的家族「继承」来的。而佐助的老师,旗木卡卡西,他虽然也有写轮眼功能,但他的写轮眼并非继承来的,事实上是他在年轻时候 include 了某位朋友的写轮眼模组,所以才有这个效果。
另一个例子,海贼王漫画里,主角鲁夫本来是普通人,但在偶然的机会下,他 include 了橡胶果实之後,他就有了橡胶人的能力了,并不是因为他老爸是橡胶人所以他才是橡胶人。
[为你自己学Ruby on Rails]https://railsbook.tw/chapters/08-ruby-basic-4.html
<<: Flutter体验 Day 4-Dart CheatSheet (2)
>>: Day 12 ( 中级 ) 猫咪跑步 ( 超长背景 )
现今的浏览器如 Firefox, Google Chrome 多以将仅 http 的网站和连结标注为...
昨天後来在看效果时,有发现过渡动画的元素已经完全超出卡片组件的范围了,这个不是我们想要的效果 理想...
不知不觉来到第16天, 今天我们要来讨论AJAX, 暂时先跳来这边, 来讲讲我经过这一个月专案, 吸...
今天要来实作灭火的行为,包含了水柱的喷射以及火焰的熄灭,那就继续看下去吧! 目录 为火焰添加碰撞器 ...
PHP函数 匿名函数 匿名函数(Anonymous functions),也称作闭包函数(closu...