计算SU平面的周长有四样写法,你知道么?
突然发现 Sketchup 中的 Face 类并没有提供返回其周长的方法,因此决定自己写一个返回周长的方法。不过前后考虑到不同的因素,换了几种实现方式,拿出来分享一下。
第一种方法:无函数版本
face.loops.collect{|loop|loop.edges.map(&:length).inject{|a,b|a+=b}}.inject{|a,b|a+=b}
这个版本的好处就是,不需要额外的跳转,一行代码之内解决所有问题,可以随时复制到需要 face 周长的方法中。不过缺点也很明显,就是可读性差,每次看到这一行都需要重新理解。另外如果多处复制使用,会降低代码的复用率,代码因此会变得臃肿。
第二种方法:函数版本
def circum(face)
res=0
face.loops.each{|loop|
res+=loop.edges.map(&:length).inject{|a,b|a+=b}
}
return res
end
通过创建一个 circum 方法,将 face 作为参数传给方法,而后返回这个平面的周长。这种做法如果在控制台中执行,就相当于定义了一个 Object 类实例的方法,在命令行中只需要这样调用:
circum(face)
如果是文件中定义则需要将其包含在模块内,然后使用如下的格式调用:
Module_name.circum(face)
这种方法是面向过程的思维,乍一看很像在写 C 或是 Pascal 之类的,函数名能够对函数本身进行解释,可读性较之前者有很大的提升。不过涉及到参数的解析,不加括号时 ruby 解析有可能出现歧义,加括号输入又不那么方便。
第三种方法:追加方法版本
module Sketchup
class Face
def circum
res=0
self.loops.each{|loop|
res+=loop.edges.map(&:length).inject{|a,b|a+=b}
}
return res
end
end
end
与前两种方法相比,这种方法相当优雅。直接在 Sketchup:: Face 类中追加一个 circum 方法,这样就可以直接用以下方式调用:
face.circum
这种方法好处在于非常的简洁,也因为这种简洁,保持了很好的可读性和输入便利性,但是这种方法毕竟不安全,如果不同的开发者都往这些类中追加自己的方法定义,很难保证不会有冲突和覆盖的情况。
第四种方法:Proc版本
ProcCircum=Proc.new{
res=0
self.loops.each{|loop|
res+=loop.edges.map(&:length).inject{|a,b|a+=b}
}
res
}
这种方法将上一种中 circum 方法的定义赋值给 ProcCircum 作为匿名函数,它本身是一个 Proc 实例,可以定义在自己模块里,这样就避免了上一种方法的冲突可能性。至于调用,可以采用以下形式:
face.instance_exec(&ProcCircum)
这里的 instance_exec 方法就是将 face 代入到 Proc 定义中的 self 来运行 Proc 中的代码。这样就在尽量保留前一种方法可读性的前提下避免了定义冲突的危险。
以上四种方法适用于不同的使用场景,各有特点和利弊,并不是说其中哪一种可以完全替代其他方案。而关于返回平面类周长这个需求,实现的方法肯定也远不止这些,哪怕是代码块中的实现方案也有不同的方案。这里仅仅是针对调用方式做了几种不同的尝试,至于为什么是四种,可能自嘲多一点吧。
本文编号:SU-2021-03