Ruby中的初始化使用的是initialize,一个默认访问限制私有的实例方法。在实例化一个Ruby对象的时候使用的是ClassName.new(paraments)的方式,那么到底new方法和initialize方法有什么区别呢?
[这个java中的构造函数有较大的区别,java中使用一个和类名同名的public 方法[如果是工厂模式或者是单例,不允许用户直接调用构造方法,可以设置为private方法]
在使用类进行初始化的时候直接使用 ClassName instanceName =new ClassName(paraments) 的方法,可以比较容易看出是直接调用了和类名相同的那个函数来完成了实例的创建。
]
首先看下一个例子:
class Foo
def initialize(val)
return 'nil' if val.zero?
end
end
puts obj = Foo.new(0) # expected nil
如果按照java的思路,够函数是不能返回值的,但是Ruby中一般的方法默认是会返回最后一行代码计算后的值。所以期望得到的应该是 nil.to_s 也就是打印字符 "nil"
当时结果却是一个Foo对象,并没有返回设想中的nil,这就引发了一个问题,到底new和initialize是不是直接调用的关系?
在stackoverflow上多番搜索,再结合《双飞燕》中对于类的描述之后,大概能得出下面的总结
主要是参考
[http://stackoverflow.com/questions/10383535/in-ruby-whats-the-relationship-between-new-and-initialize-how-to-return-n]:
1. new 是一个类方法,产生一个类的实例(在后台中负责处理复杂的内存分配等工作,在java中构造函数在执行过程中完成对内存的分配?[猜测等待考究])
2. initialize则是以个实例方法,更具参数条件设置内部声明的值[一般为实例参数],如果没有指定的话,是一个被private方法修饰的方法,也就是说如果没有特殊指定一个类依靠点方法是无法访问得到initailize的。
3.二者都可以被重写,比如Foo.new 可以放回Foo的一个子类
二者之间的关系实现类似于
Class Class
def new(*args,&block)
obj = allocate #分配内存指定object_id
obj.initizlize(*args,&block)
#使用obj.send(:initialize,...)的放射方法
obj
end
end
在Ruby中,方法都会放回也只有方法才会返回值,而new和initialize之间的调用关系也正是导致第一段代码没有按照预期执行的原因,
我们重写了initailize,并放回一个字符串‘nil’,然而我们在初始化一个实例的时候,调用的是类方法new 放回的是一个Foo的instance,如果我们想要调用new来实现代码一种的期望,那就只能重载类方法new
class Foo
def self.new(val)
return nil if val.zero?
super
end
end
但是new作为创建一个对象的初衷显然已经被破坏了,一个糟糕的实践。
最后的总结就是 new是通过调用initialize产生了一个对象实例,而不是直接由initialize来返回产生的对象。对于new方法,也应该尽量避免重载去破坏产生一个完整类的初衷。