短:
有没有办法创建扩展Array
类名为 A
, 支持完整的方法链 map
, sort
, sort_by
和新方法word
并且不会伤害Array
类(class)?
示例:
[
A.new(a).word,
A.new(a).sort.word,
A.new(a).sort_by(&:-@).word,
A.new(a).map(&:chr).sort.map(&:ord).word
]
长话短说:
我解决了这个 kata并创建了扩展 Array
的代码类与新 word
方法:
class Array
def word
[*self[0..1],*self[-2..-1]].map(&:chr).join
end
end
def sort_transform(a)
[
a.word,
a.sort.word,
a.sort_by(&:-@).word,
a.map(&:chr).sort.map(&:ord).word
].join ?-
end
然后我认为为此类基类添加方法不是一个好主意。我试图实现一个新类,它继承了 Array
的所有行为。 .
class A < Array
def word
[*self[0..1],*self[-2..-1]].map(&:chr).join
end
end
这个添加破坏了我的代码,因为 map
, sort
, sort_by
返回 Array
实例:A.new([1,2,3]).sort.class # Array
.并且 Array 不理解 word
方法。而不是 A.new(a).sort.word
我必须将链的一部分封装到 A.new
中构造函数:A.new(a.sort).word
.这肯定会打破纯方法链。
是否可以扩展 Array
这样可以达到像这样的纯方法链; A.new(a).sort.word
?
当我试着写这行时: A类<数组
def word
[*self[0..1],*self[-2..-1]].map(&:chr).join
end
def sort
A.new(self.sort)
end
end
这给我带来了 main.rb:8:in 'sort': stack level too deep (SystemStackError)
终于写完这行我找到了避免深度堆栈的方法:将 self 转换为 Array
然后再次将其转换为 A
.
class A < Array
def word
[*self[0..1],*self[-2..-1]].map(&:chr).join
end
def sort
A.new(self.to_a.sort)
end
end
那么它是实现这种扩展的唯一方法吗?
最佳答案
如果您曾经想对核心类进行 monkey-patch,但您认为它很恶心,您应该记住,改进只是针对这种情况。
module ArrayWithWord
refine Array do
def word
[*self[0..1],*self[-2..-1]].map(&:chr).join
end
end
end
class WordTest
using ArrayWithWord
# [].word works here
def self.sort_transform(a)
[
a.word,
a.sort.word,
a.sort_by(&:-@).word,
a.map(&:chr).sort.map(&:ord).word
].join ?-
end
end
WordTest.sort_transform(%w(foo bar baz quux))
# => "fbbq-bbfq-bbfq-bbfq"
# [].word doesn't work here
[].word
# => NoMethodError (undefined method `word' for []:Array)
关于arrays - 支持完整方法链的 Ruby Extended Array 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56881329/