Ruby enumerables不保持同一个类
我有一个代表集合的类.我将Enumerable模块包含在其中并定义了方法#each,以便我获得所有方法.
但问题是Enumerable的方法不能保持同一个类.所以,例如,如果我的类名为Collection,如果我做Collection #select,我希望结果的类也是Collection(而不是Array).有没有办法如何实现这一目标? 解决方法
不幸的是,Ruby的Collection Operations不是类型保留的.每个集合操作始终返回一个Array.
对于像集合或树的集合,这只是令人讨厌,因为您需要始终将它们转换回您想要的类型.但是例如对于所有素数的无限懒惰流,这是灾难性的:你的程序将挂起或耗尽内存试图构造一个无限大的数组. 大多数Collection API要么消除重复的代码,要么保留类型,但不能同时保留两者.例如. .NET的Collection API主要消除了重复的代码,但它总是返回相同的类型:IEnumerable(相当于Ruby的Enumerator). Smalltalk的Collection API是类型保留的,但它通过复制每个Collection类型中的所有Collection Operations来实现这一点. 唯一保留类型但却消除重复的Collection API是Scala.它通过引入Collection Builders的新概念来实现这一点,Collection Builders知道如何有效地构建特定类型的Collection.收集操作是根据Collection Builders实现的,只有Collection Builders需要复制……但这些都是特定于每个Collection的. 如果你想在Ruby中保留类型保存的Collection操作,你需要复制你自己的Collection中的所有Collection Operations(这将仅限于你自己的代码),或者重新设计整个Collection API以使用Builders(这需要重大的重新设计)不仅是您自己的代码,还包括现有的集合,包括所有第三方集合. 很明显,第二种方法至少是不切实际的,如果不是不可能的话.第一种方法也存在问题:收集操作有望返回数组,违反了预期可能会破坏其他人的代码! 您可以采用类似于Ruby 2.0的惰性集合操作的方法:您可以向API添加一个新方法preserve_type,它返回一个具有类型保留Collection Operations的代理对象.这样,代码中明确标出了对标准API的偏离: c.select … # always returns an Array c.preserve_type.select … # returns whatever the type of c is 就像是: class Hash def preserve_type TypePreservingHash.new(self) end end class TypePreservingHash def initialize(original) @original = original end def map(*args,&block) Hash[@original.map(*args,&block) # You may want to do something more efficient end end (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |