如何在不使用new的情况下在Ruby中创建对象

时间:2014-06-22 12:26:57

标签: ruby constructor

可以使用

在Ruby中创建一个复数
c = Complex.new(1,2)

但是,它可以缩短为

c = Complex(1,2)

是否可以实现相同的功能而无需在类外定义函数,如下例所示?

class Bits
  def initialize(bits)
    @bits = bits
  end
end

def Bits(list) # I would like to define this function inside the class
  Bits.new list
end

b = Bits([0,1])

我认为Ruby应该允许至少一个下面提出的构造函数

class Bits
  def initialize(bits)
    @bits = bits
  end

  def self.Bits(list) # version 1
    new list
  end

  def Bits(list)      # version 2
    new list
  end

  def Bits.Bits(list) # version 3
    new list
  end
end

5 个答案:

答案 0 :(得分:5)

有这个片段:

def make_light_constructor(klass)
    eval("def #{klass}(*args) #{klass}.new(*args) end")
end

现在你可以这样做:

class Test
    make_light_constructor(Test)
    def initialize(x,y)
        print x + y
    end 
end

t = Test(5,3)

是的,我知道您仍在定义类外的函数 - 但它只是一个函数,现在您想要的任何类都可以使用它的实现,而不是每个类创建一个函数。

答案 1 :(得分:4)

c = Complex(1,2)

实际上正在调用a method on Kernel

答案 2 :(得分:2)

基本上你不能在Ruby(Complex class is written in C)中覆盖 - ()运算符。

您可以使用[]:

实现类似的功能
class Bits
  def self.[](list)
    Bits.new list
  end
end

这将允许类似:

b = Bits[[1,2]]

答案 3 :(得分:1)

如果将类打包到某个模块中,则可以使用2种方法:

  • self.included - 当您include Mod
  • 时调用
  • self.extend - 当您extend Mod
  • 时调用

我使用self.included创建了非常基本方法。

缺点:很难写。你可以说它很复杂;它可能不包含所有功能 优点:它看起来像<{1}} 完全(它使用Complex(2,3)代替(),如https://stackoverflow.com/a/24351316/2597260答案);您只需创建[]initialize即可创建其余内容。

self.included

答案 4 :(得分:0)

this blog post的启发,这是您可以(但不应)使用的另一种骇客:

def method_missing(sym, *args, **kwargs, &blk)
    Object.const_get(sym).new(*args, **kwargs, &blk)
end

这只是希望任何未知的方法名称都是类的名称,并在该类上调用:new

具有基本的错误处理:

alias sys_method_missing method_missing

def method_missing(sym, *args, **kwargs, &blk)
    cls = Object.const_get(sym) if Object.constants.include? sym
    if cls.is_a?(Class) then cls.new(*args, **kwargs, &blk)
    else sys_method_missing(sym, *args, **kwargs, &blk) end
end

如果未知的方法名称是类的名称,则会在类上调用:new。否则,它将调用委托给method_missing()的原始实现。

用法:

class Foo
end

foo = Foo()
p foo

结果:

#<Foo:0x00007f8fe0877180>