
拆分和重构(Destructuring)
你或许会对ruby的合成/拆分符印象深刻,例子如下:
同样,可以在赋值时进行这样的操作,下一个例子中,将拆分一个区间(Range),同时,将拆分后中间的元素收集到body中合成一个数组。
当进行并行赋值时,如果右值是一个数组,则会被自动拆分。当你有一个方法返回一个数组时,这种方式很有效。
你同样可以利用这种方式获取数组的第一个元素。
然而,可以使用实例方式first以更优雅的方式来获。
你可以利用哈希(Hash)的values_at实例方法来返回一个数组。
在传递代码块参数的时候将发生隐式拆分。
使用括号你可以更深的层次拆分。
方法在传递参数的时候这种方式同样可行!
在Ruby中,你可以通过两种方式实现这种拆分的功能.第一种方式,你可以通过‘*’作用与一个对象。调用对象的to_a实例方法进行拆分。
第二种方式,对于隐式拆分,需要使用to_ary实例方法。你可以选择性的实现这个方法,由于它会使你的对象在你没有预料到的地方突然表现出像数组(Array)一样的行为。
最后一种使用‘*’符的特殊情形,是在子类覆写的方法中使用super调用父类的同名方法。
事实上,你没有必要写一大堆为了增加附加行为的参数,你只需要传递一个‘*’,在方法中仅仅使用super,就可以把所有参数传递给父类方法。
转换方法(Conversion methods)
我们刚刚看到,可以通过显式或隐式的方法将一个对象转换为一个数组(Array).。这些方法可以被认为是严格或非严格的转化方法,其他的类型同样也有一些这样的方法。
非严格的转换方法你或许知道一些,,例如#to_a, #to_i,#to_s以及Ruby2.0中的#to_h和少数的其他方法。大多数类型都具有这些方法,包括nil。
有时,这些非严格的转换方法会使你犯某些错误,例如,传递一些非法的数据使系统崩溃,返回一些错误的结果,或者产生一些意想不到的错误。
对于一些类型Ruby提供了更加严格的转化方法,例如,#to_ary, #to_int, 以及#to_str。
这些方法只在对严格转换敏感的特定类中实现,例如,实例方法#to_int只对于数字类可用。
这种方式更好一点,我们在合适的地方获得了一个异常,但是这个异常并不能很好表达我们的意图。
另外,由于String类没有实现实例方法#to_int,对于String类我们需要覆写原始的方法。
但是Ruby拥有另一系列转换方法,这些方法更加智能。这些方法中,最有用的方法是Array()和Integer()(同时还有其他转换方法例如Float())。其他一些方法例如String()和Hash()使用情况较少,他们仅仅是代理到实例方法#to_s和实例方法#to_h。
现在我们的例子将抛出一个异常可以很好展示我们的意图,另外我们也可以使用字符串。
这也是Integer()方法更加优雅的地方。
Array()同样非常有用,当它不能将参数转换成一个数组时,它将把参数放到一个空数组
中。
偶尔,你需要定义一个方法接受一个对象或者一个对象数组,你可以使用Array()而避免明确的类型检查。
正如上面提到的实例方法#to_ary,这类转换方法中的一些被Ruby解释器内部使用,这些方法是严格转换方法,同样也可以作为隐式转换方法。由于它们是严格的所以可以被作为隐式转换方法所使用。
这些方法在Ruby中被广泛的使用,例如实例方法#to_int用来将传递给Array#[]的参数转换为int,当raise的参数不是一个Exception对象时,实例方法#to_str用来将被用来转换。
最后一个要提到的转换方法是#to_proc。这个方法在一个方法的参数中使用一元符‘&’时将被调用。
在一个方法调用中,‘&’将一个Proc对象转换为一个block参数。
如果‘&’直接作用于一个参数,则会隐式调用实例方法#to_proc将操作数转变为一个block。
在Ruby代码中,一种非常常见的做法是将其作用于一个Symbol对象。
这中方式内建于Ruby1.9以后的版本,对于以前的版本你可以像这样自己实现:
下面的例子使用实例方法#to_proc和‘&’来从一个数组(Array)初始化Point对象。