計算SU平面的周長有四樣寫法,你知道么?
突然發(fā)現(xiàn) Sketchup 中的 Face 類并沒有提供返回其周長的方法,因此決定自己寫一個返回周長的方法。不過前后考慮到不同的因素,換了幾種實現(xiàn)方式,拿出來分享一下。
第一種方法:無函數(shù)版本
face.loops.collect{|loop|loop.edges.map(&:length).inject{|a,b|a+=b}}.inject{|a,b|a+=b}這個版本的好處就是,不需要額外的跳轉(zhuǎn),一行代碼之內(nèi)解決所有問題,可以隨時復制到需要 face 周長的方法中。不過缺點也很明顯,就是可讀性差,每次看到這一行都需要重新理解。另外如果多處復制使用,會降低代碼的復用率,代碼因此會變得臃腫。
第二種方法:函數(shù)版本
def circum(face)res=0face.loops.each{|loop|res+=loop.edges.map(&:length).inject{|a,b|a+=b}}return resend
通過創(chuàng)建一個 circum 方法,將 face 作為參數(shù)傳給方法,而后返回這個平面的周長。這種做法如果在控制臺中執(zhí)行,就相當于定義了一個 Object 類實例的方法,在命令行中只需要這樣調(diào)用:
circum(face)如果是文件中定義則需要將其包含在模塊內(nèi),然后使用如下的格式調(diào)用:
Module_name.circum(face)這種方法是面向過程的思維,乍一看很像在寫 C 或是 Pascal 之類的,函數(shù)名能夠?qū)瘮?shù)本身進行解釋,可讀性較之前者有很大的提升。不過涉及到參數(shù)的解析,不加括號時 ruby 解析有可能出現(xiàn)歧義,加括號輸入又不那么方便。
第三種方法:追加方法版本
module Sketchupclass Facedef circumres=0self.loops.each{|loop|res+=loop.edges.map(&:length).inject{|a,b|a+=b}}return resendendend
與前兩種方法相比,這種方法相當優(yōu)雅。直接在 Sketchup:: Face 類中追加一個 circum 方法,這樣就可以直接用以下方式調(diào)用:
face.circum這種方法好處在于非常的簡潔,也因為這種簡潔,保持了很好的可讀性和輸入便利性,但是這種方法畢竟不安全,如果不同的開發(fā)者都往這些類中追加自己的方法定義,很難保證不會有沖突和覆蓋的情況。
第四種方法:Proc版本
ProcCircum=Proc.new{res=0self.loops.each{|loop|res+=loop.edges.map(&:length).inject{|a,b|a+=b}}res}
這種方法將上一種中 circum 方法的定義賦值給 ProcCircum 作為匿名函數(shù),它本身是一個 Proc 實例,可以定義在自己模塊里,這樣就避免了上一種方法的沖突可能性。至于調(diào)用,可以采用以下形式:
face.instance_exec(&ProcCircum)這里的 instance_exec 方法就是將 face 代入到 Proc 定義中的 self 來運行 Proc 中的代碼。這樣就在盡量保留前一種方法可讀性的前提下避免了定義沖突的危險。
以上四種方法適用于不同的使用場景,各有特點和利弊,并不是說其中哪一種可以完全替代其他方案。而關于返回平面類周長這個需求,實現(xiàn)的方法肯定也遠不止這些,哪怕是代碼塊中的實現(xiàn)方案也有不同的方案。這里僅僅是針對調(diào)用方式做了幾種不同的嘗試,至于為什么是四種,可能自嘲多一點吧。
本文編號:SU-2021-03
