Ruby:从Array类中提取Stack的功能

Hun*_*len 4 ruby stack

我需要为我正在编写的程序使用类似堆栈的数据结构,并且我知道Ruby没有显式的堆栈数据结构,但是Array类具有构成堆栈的所有属性:push,pop,size,clear,isEmpty,inspect,to_s.

在线搜索我发现使用这种语法的各种帖子将Array类的功能提取到子类中:

Stack = Array.extract([
  :push,
  :pop,
  :size,
  :clear,
  :inspect,
  :to_s
])

s = Stack.new
s.push 1
s.push 2
s.push 3
s       # => [1, 2, 3]
s.pop   # => 3
s       # => [1, 2]
Run Code Online (Sandbox Code Playgroud)

我想做类似的事情所以我的Array子类在它可以进行的调用中受到限制,但似乎提取方法不再在Array类API中.

问题:

  1. 这个功能被移除是有原因的,这样的事情有什么损害?
  2. 如何使用Ruby 1.9.3实现与此类似的功能?现在我只是将我需要的调用委托给Array类,但Array类中的所有其他方法仍然可以在我的Stack对象上调用,我不想允许.

Ser*_*sev 8

拿这个代码,例如:

class Stack
  def initialize
    @array = []
  end

  def push val
    @array.push val
  end

  def pop 
    @array.pop
  end
end
Run Code Online (Sandbox Code Playgroud)

这里有私有实例var,您委派所选方法.其他方法不能直接调用.语法可以变甜,并通过一些元编程更加"rubesque",但基本思想如上所示.

当然,人们总是可以通过这种私人变换来获取它,instance_variable_get而你无能为力.这是Ruby!

制作干净安全的公共界面.如果有人试图干涉内在部分并打破某些东西,那就是他的问题.

更新

如果你正在使用ActiveSupport(随Rails一起提供),那么有一种更简单的方法.

# load ActiveSupport if not in Rails env
require 'active_support/core_ext'

class Stack
  def initialize
    @impl = []
  end

  # the "extract" part :)
  delegate :count, :push, :pop, to: :@impl
end

s = Stack.new
s.push(3).push(4)
s.count # => 2
Run Code Online (Sandbox Code Playgroud)

或者看看@AndrewGrimm的类似答案.