Ruby 板


LINE

所谓 multi-method/dispatch 为动态决议两种以上真实型别的手段 在一般的物件导向程式语言中,仅仅支援 single-method/dispatch, 亦即 ooo.xxx(); 我们会说,我们 send 了 xxx 这个 message 给这个 ooo, 但这个 ooo 是什麽我们不知道,我们只知道他会依照 xxx 这个 message 来唤起正确的 method, 亦即 ooo 真实型别的 method. 於是我们可以不在乎 ooo 的真实型别,却能相信他能找到正确的 method. 尽管我相当不认同「一般所谓物件导向的三样特性」,不过依照这个说法的话, 这正是该三样特性的第三样:polymorphism, 多形。 p.s. 我个人认为 dynamic binding 动态连结会是比较好的说法,anyway, off-topic 而如果我们需要决议两种以上的型别呢? 例如: unit.walk_to(dist); 假设每个 unit 都有不同的特性,所以在走到各种不同的 dist 上都会有 不同的效果。其实这可以用一个很简单的查表法来取得所需的数值,例如: UnitA UnitB UnitC TerrainA 100 200 300 TerrainB 50 700 12 TerrainC 777 666 999 除了数字以外,也可以把所有要的资料打包起来放到这个 table 中。 不过这样做的话,就必须维持各种不同的 id, 而且最重要的是, 如果所需的不只是资料不同,而是整个结果都完全不同呢? 例如当 UnitA 碰上 TerrainA 时,其实是要踩到地雷的,那不单单只是资料问题 我们希望的应该是,写下 unit.walk_to(dist); 时,除了 unit 是已知型别外, dist 也应该要是已知型别,walk_to 才会知道到底该怎麽做。 在不支援 multi-method/dispatch 的程式语言中,一般我们可能会这样写: C++: void UnitA::walk_to(Terrain* dist){ if( TerrainA* terrain = dynamic_cast<TerrainA*>(dist) ){ // do something with UnitA v.s. TerrainA } else if( TerrainB* terrain = dynamic_cast<TerrainB*>(dist) ){ // do something with UnitA v.s. TerrainB } else{ // do something with UnitA v.s. // terrain which you don't care who it is } } Java: void walk_to(Terrain dist){ if( dist instance_of TerrainA ){ TerrainA terrain = (TerrainA)dist; // do something with UnitA v.s. TerrainA } else if( dist instance_of TerrainB ){ TerrainB terrain = (TerrainB)dist; // do something with UnitA v.s. TerrainB } else{ // do something with UnitA v.s. // terrain which you don't care who it is } } 也就是,一个个去检查他们到底是什麽型别。当然,这绝对是个很暴力的做法, 就像我们极力去避免的 switch case 一样,最大的缺点就是 error-prone. 我看过好几个 C++ 的解决方法,Loki 的做法大概有两个,一个就是像上面的 暴力法,不过是自动化的,所以可以确保不会 error-prone. 缺点就是你很容易 碰到很可怕的编译问题,这边不继续讨论。 另一个做法就是建立一个 map(Hash),用 type_info 做索引,对应到一个注册 好的 method. 用起来大概像这样: dispatcher(unit, dist); 於是 dispatcher 用 typeid 取得 unit 和 dist 的 type_info, 再由这两个 type_info 组成的 key 去寻找当初注册好的 method. 本文的重点就是这个方法,请看到这个: http://rubyforge.org/projects/multi/ 这是 Ruby 的 multi-method/dispatch 的 lib, 他的实作法就跟这个做法类似 不过在讲这个重点前,再来看看另外一个实作法,我觉得相当有趣。 简单地说,当我们说:「unit.walk_to(dist)」时,是否可以获得 unit 的真实 型别?那麽,何不故技重施,以便获得第二个真实型别? 避免写太长不好阅读,待续… --   『风车』が廻り続ける度に 『美しき』幻想が静かに纺がれ    『焔』の揺らめきの外に 『腕』を伸ばす愚かな者达 -《Roman》5th Story  『宝石』をより多く掴もうと 『朝と夜』の狭间を彷徨い続ける Track 10   『星屑』の砂の煌めきにも 『葡萄酒』の仄甘い陶酔を魅せ 黄昏の贤者 『贤者』が忌避する槛の中から 『伝言』の真意を彼等に问うだろう   『天使』が别れを告げし时 『地平线』は第五の物语を识る --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 61.217.103.191







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Boy-Girl站内搜寻

TOP