您的位置:首页 > 其它

Scala学习笔记(八)----类型问题

2016-06-29 14:28 459 查看
先看一段 java代码public class test
{

public static void main(String[] args) throws ClassNotFoundException, SQLException
{
List<Pet> list = new ArrayList<Pet>();
list.add(new Dog("Limbo",1));
list.add(new Dog("Yu",1));
workWithPets(list);
}
public static void workWithPets(List<Pet> list)
{
for(Pet p : list)
{
System.out.println(p);
}
}
}
class Pet{
private String name;
private int age;
public Pet(){}
public Pet(String name,int age)
{
this.name = name;
this.age = age;
// TODO Auto-generated constructor stub
}
@Override
public String toString()
{
return "name: "+ this.name +" age: "+ this.age;
}
}
class Dog extends Pet{
public Dog(String name,int age)
{
super(name,age);
// TODO Auto-generated constructor stub
}
}OK,这一段代码编译执行均无问题
接下来让我们看一段Scala代码

class Pets(var name:String,var age:Int) {
override def toString() :String = {"name: " + name + " age: " + age}
}
class Dog(override var name:String,override var age:Int )extends Pets(name, age)
{}

object test3{
def main(args: Array[String]): Unit = {
val dogs = Array(new Dog("Limbo",1),new Dog("Yu",2))
workWithPets(dogs) //Compiling Error
}
def workWithPets(pets:Array[Pets])={
pets.foreach(println)
}
}
调用workWithPets()的时候,Scala会提示错误,Dog数组不能穿给接收Pet数组的方法,但是,对这个方法而言,这么做没有什么不良后果。不过Scala不知道这一点,它试图保护我们。我们需要做的就是告诉Scala这样做是可行的
def workWithPets[T <: Pet](pets:Array[T])={
pets.foreach(println)
}这里用特殊的语法定义了workWithPets()。 T <: Pet 表示T所代表的类派生自Pet。通过使用这种上界语法,我们告诉Scala,具有参数化类型T的类型T的参数数组必须至少是Pet的数组,也可以是Pet的派生类的数组。
协变:将子类实例的容器赋给基类容器的能力

逆变:将超类实例的容器赋给子类容器的能力

例子:

如果一个方法要接受Dog参数,那么另一个接受Animal参数的方法肯定也可以接受这个方法的参数,这是Animal向Dog方向的转变是逆变。如果一个方法要求的返回值是Animal,那么返回Dog的方法肯定是可以满足其返回值要求的,这是Dog向Animal方向的转变是协变。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: