将initialize方法重命名为更友好的init

时间:2016-03-26 23:48:41

标签: ruby-on-rails ruby rubygems

最好的方法将ruby中的长'初始化' 方法重命名为 Objective-C ' init' ,以便在任何类定义中我们可以说

def init
end 

而不是

def initialize 
end

更新

我想创建一个初始化的init,并接受传递给Object.new的参数和块(* args,& block)我需要一个名为init的典型初始化方法.new调用而不是初始化,以便我可以通过它传递参数并阻止它到原始参数。嗯寻找与对象创建挂钩并初始化自身的东西。某种回电。

更新2

我已将正确的答案转换为宝石检查出来......

https://rubygems.org/gems/new_init

4 个答案:

答案 0 :(得分:4)

到目前为止,最好的方法是不要这样做。额外的6个字符不会杀死你,非常值得拥有,以保持你的红宝石惯用。但是,如果你真的想,你可以用猴子修补来做到这一点:

# Monkey patch BasicObject (which your class will inherit from) such that
# it's initialize method just passes on params to init
class BasicObject
  def initialize(*args)
    init(*args) if respond_to? :init
  end
end

class MyClass
  def init(test1, test2)
    puts "Params are: #{test1}, #{test2}"
  end

  def say_hello
    puts "Hello from a class that uses init rather than initialize"
  end
end

x = MyClass.new('Hello', 'World')
x.say_hello

只是为了重新迭代,这是一个坏主意。不要这样做。

答案 1 :(得分:3)

如果不改变语言规范,就不可能做到这一点。

但首先,我会向您展示 的可能性。

#initialize调用

Class#newClass#new基本上看起来像这样:

class Class
  def new(*args, &block)
    obj = allocate
    obj.initialize(*args, &block)
    obj
  end
end

默认情况下initializeprivate,因此实际需要执行此操作:

class Class
  def new(*args, &block)
    obj = allocate
    obj.__send__(:initialize, *args, &block)
    obj
  end
end

现在,您可以立即明确更改方法名称所需的操作:只需将monkeypatch Class#new调用init而不是initialize

class Class
  def new(*args, &block)
    obj = allocate
    obj.init(*args, &block)
    obj
  end
end

轰!你已经完成了。

然而,这不等同于!请注意我上面的说法默认情况下initializeprivate?那"魔术"!名称initialize与其他方法不同,默认情况下为public,默认情况下名为initialize的方法为private

class Foo
  def initialize; end
  def init; end
end

Foo.private_instance_methods(false)
#=> [:initialize]

Foo.public_instance_methods(false)
#=> [:init]

这是Ruby语言规范的一部分,无法在Ruby中表达。

另请注意,既然您已将monkeypatched Class#new调用init而不是initialize,则需要重命名系统中的每个现有initialize方法,否则,他们不会被召唤!

ObjectSpace.each_object(Module).
  select {|m| m.instance_methods(false).include?(:initialize) }.
  each do |m|
    m.alias_method :init, :initialize
  end

class Class
  def new(*args, &block)
    obj = allocate
    obj.init(*args, &block)
    obj
  end
end

ObjectSpace.each_object(Module).
  select {|m| m.instance_methods(false).include?(:initialize) }.
  each do |m|
    m.remove_method :initialize
  end

这段代码几乎肯定会破坏任何真实世界的程序,因为依赖名称initialize已经深深地融入现有的Ruby代码和Ruby文化中。

答案 2 :(得分:1)

class Object
  #alias_method :native_initialize, :initialize
  def initialize
    #native_initialize
    init if respond_to? :init
  end
end

class Duck
  def init
    p "QUA QUA"
  end
end

Duck.new

答案 3 :(得分:0)

无代码initialize方法?什么都不做。

class Foo
 # no meaningful initialize
end