在我们使用某些编程语言开发时,有些时候总是希望函数(方法)返回多个值。一般情况下我们有几种选择,下面我们以Java为例。
- 将返回值作为参数参入函数或者方法,然后修改实参,这样就相当于“返回值”。如:
public void func1(String arg1,String arg2){
arg1 = "abc";
arg2 = "bcd";
}
这种方式代码比较丑陋,不美观,而且对于int,double等字面量是无效的。
2. 将返回值封装成对象(结构体)。如:
public ReturnType func2(){
ReturnType result = new ReturnType("abc","bcd");
return result;
}
class ReturnType{
private String arg1;
private String arg2;
public ReturnType(String arg1, String arg2) {
this.arg1 = arg1;
this.arg2 = arg2;
}
public String getArg1() {
return arg1;
}
public void setArg1(String arg1) {
this.arg1 = arg1;
}
public String getArg2() {
return arg2;
}
public void setArg2(String arg2) {
this.arg2 = arg2;
}
}
使用这种方式,代码量比较大,而且程序显得臃肿不堪。上例中,我们只是为了同时返回两个返回值,而我们却要定义返回值类型,并且封装返回值数据。对于一般java bean来说,还需要setter和getter方法。所以代码非常臃肿。
Scala解决了我们这个困惑,在Scala中包含了TupleN(N代表1-22之间整数)类。TupleN代表N元素组,一般以效果好加逗号分隔。TupleN表示多个类各自独立.
对于上述例子中,我们只需要定义一个Tuple2即可,如:
def func3() : Tuple2[String,String] ={("abc","bcd")}
在java中近30行的代码量Scala只需要一行代码即可实现,可见其间接性。
TupleN的实例是不可变的,所以我们可以将他们赋值给变量,将他们作为输入参数或则从方法中返回。而对于Tuple的使用,也是非常灵活,尤其配合Scala的类型推导,我们可以用很少的代码实现很强大的功能。下面我们来详细演示Tuple的实际操作
class TupleExample {
def main(args: Array[String]): Unit = {
val t= ("hello",1,2.3)// 用字面量构造一个三个参数的Tuple3
println("print the whole tuple:" + t)
println("print the first item" + t._1)//从Tuple中取第一个元素
println("print the second item" + t._2)//从Tuple中取第二个元素
println("print the third item" + t._3)//从Tuple中取第三个元素
val(t1,t2,t3) = ("world",'!',0x22)//声明三个变量,用Tuple中三个元素分别赋值
println(t1 + "," + t2 + "," + t3)
val(t4,t5,t6) = Tuple3("world",'!',0x22)//使用Tuple3的工厂方法构造一个元素
println(t4 + "," + t5 + "," + t6)
}
val t7 = "abc" -> 23;//定义Tuple2的其他方式
}
从代码中我们可以看出:
- Tuple中元素的类型不需要一致,我们可以将String,Int,Double等元素存放于同一个元组。
- Tuple中取元素时与我们一般编程语言计数是有差异的。在其他编程语言中,计数是从0开始的。如我们访问Java中数组的第一个元素必须这样写“数组名[0]”,但是在Scala的Tuple中,取第一个元素时从1开始计算。如t._1。(不要忘记下划线)
- 构造Tuple的方式:我们一般可以直接使用字面量来构造Tuple,如val t= (“hello”,1,2.3),这与Java中构造数组类似。也可以通过new关键字,如val t= new Tuple3(“hello”,1,2.3),这与上述代码效果是一样的。Scala中还有一种构造对象的方法Tuple3(“hello”,1,2.3),这看上去只是比在上述第二种构造方式中缺省了new关键字。其实不然,这是Scala中比较有用的语法,这涉及到伴生对象以及apply的使用,我们后续讨论。在这里我们只需要明白,并不是Scala构建对象时new是可以省略的。对于这种语法,是Scala使用其他语法,我们可以理解这种方法是Scala构建对象的工厂方法。
- val(t1,t2,t3) = (“world”,’!’,0x22),对于这样的代码,可以理解为定义了t1,t2,t3三个变量,并且用Tuple3的元素为其逐个赋值。这种方式也可以理解为从Tuple3中提取各个元素。
- 如果Tuple只有两个元素,即Tuple2的对象,我们也称之为pair,对于Tuple2这种类型,我们还有其他构造方式。如val t7 = “abc” -> 23。使用“箭头操作符”与上述三种构造方式其实是一样的效果。