可以使用
在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
答案 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>