zoukankan      html  css  js  c++  java
  • 类型参数

    泛型Generic Type

    Generic :一般的,普通的;通用的,不专用的;非专用装置的;非特有的

    方法或者类可以接受任何类型的参数,参数类型只有在使用的时候或者调用的时候才被确定,类.特质.函数都可以有类型参数。

    泛型可以使方法或者类更加通用。

    泛型类:

    scala> class fruit[A,B](var name:A,var price:B){println(s"I love $name,but $price dolar is too high!")}
    defined class fruit

    scala> val apple=new fruit[String,Int]("apple",5)
    I love apple,but 5 dolar is too high!
    apple: fruit[String,Int] = fruit@1e7113f8

    scala> val apple=new fruit("apple",5)
    I love apple,but 5 dolar is too high!
    apple: fruit[String,Int] = fruit@7adf8932

    scala> val banana=new fruit[String,String]("banana","five")
    I love banana,but five dolar is too high!
    banana: fruit[String,String] = fruit@6d4062fd

    泛型函数

    scala> def method[T](arr:Array[T]){arr.foreach(println)}
    method: [T](arr: Array[T])Unit

    scala> method[Int](Array(1,2,3))
    1
    2
    3

    scala> method[String](Array("one","two","three"))
    one
    two
    three

    scala> method(Array('a','b',1))
    97
    98
    1

    scala> method(Array('a','b',"aaa"))
    a
    b
    aaa

    ----------------------------
    scala> 1.compareTo(100)
    res8: Int = -1

    scala> 1.compareTo(1)
    res9: Int = 0

    scala> 1.compareTo(-100)
    res10: Int = 1

    ---------------------------------

    类型变量界定

    Java中, (? extends T), T称为上界, 比较容易理解, 代表T和T的子类, (? supers T), T称为下界

    Scala中, 界却用于泛型类中的方法的参数类型上

    对类型变量进行限制

    scala> def compare[T1](a:T1,b:T1){if(a.compareTo(b)>=0)println(">=") else println("<")}
    <console>:11: error: value compareTo is not a member of type parameter T1
    def compare[T1](a:T1,b:T1){if(a.compareTo(b)>=0)println(">=") else println("<")}
    ^

    这是错误的,我们并不知道a是否有compareTo方法。

    要解决这个问题,我们可以添加一个上界 T <: Comparable[T] :

    scala> def compare[T<:Comparable[T]](a:T,b:T){if(a.compareTo(b)>=0)println(">=") else println("<")}
    compare: [T <: Comparable[T]](a: T, b: T)Unit

    scala> compare[String]("100","50")
    <

    scala> compare[String]("tdd","mn")
    >=

    scala> compare[Int](100,50)
    <console>:13: error: type arguments [Int] do not conform to method compare's type parameter bounds [T <: Comparable[T]]
    compare[Int](100,50)
    ^

    Int不是Comparable[Int]的子类,Scala Int类型没有实现Comparable接口

    scala> compare[BigInt](100,50)
    >=

    scala> class compare[T<:Comparable[T]](a:T,b:T){def smaller()={ if(a.compareTo(b)<0) a else b;}}
    defined class compare

    scala> val comp=new compare[String]("gg","ss")
    comp: compare[String] = compare@706243d4

    scala> val comp=new compare[String]("gg","ss")
    comp: compare[String] = compare@706243d4

    scala> val comp=new compare[BigInt](100,50)
    comp: compare[BigInt] = compare@2443ac97

    scala> comp.smaller
    res33: BigInt = 50

    上界:

    只允许T的超类U来替换T。 [U >: T]

    下界:

    只允许T的子类U来替代T。 [U <: T]

    视图界定

     部分类型不是Comparable[Int]的子类,导致报错,解决方法就是视图界定

    <%关系意味着T可以被隐式的转换为Comparable[Int]

    scala> class compare[T<%Comparable[T]](a:T,b:T){def smaller()={ if(a.compareTo(b)<0) a else b;}}
    defined class compare

    scala> val comp=new compare[String]("gg","ss")
    comp: compare[String] = compare@1516d85a

    scala> comp.smaller
    res34: String = gg

    scala> val comp=new compare[Int](100,50)
    comp: compare[Int] = compare@889cd2f

    scala> comp.smaller
    res35: Int = 50

    上下文界定

     上下文界定形式 T:M,其中M是另一个泛型类,它要求必须有一个类型为M[T]的"隐形值"

    scala> class pair[AA:Ordering](val f:AA,val s:AA){ def smaller(implicit ord:Ordering[AA])={ if (ord.compare(f,s)<0) f else s;}}
    defined class pair

    scala> val p1=new pair[BigInt](100,200)
    p1: pair[BigInt] = pair@4cea9399

    scala> p1.smaller
    res164: BigInt = 100

    scala> val p1=new pair[BigInt](100,20)
    p1: pair[BigInt] = pair@4728b5f5

    scala> p1.smaller
    res165: BigInt = 20

    scala> val p1=new pair(100,20)
    p1: pair[Int] = pair@68694894

    scala> p1.smaller
    res166: Int = 20

    scala> val p1=new pair("aa","bb")
    p1: pair[String] = pair@be81a18

    scala> p1.smaller
    res167: String = aa

    scala> val p1=new pair("aa",100)
    <console>:18: error: No implicit Ordering defined for Any.
    val p1=new pair("aa",100)
    ^

     Manifest上下文界定

    实例化一个Array[TT]对象,就需要一个Manifest[TT]对象

    scala> def makarr[TT:Manifest](f:TT,s:TT)={ val arr=new Array[TT](2);arr(0)=f;arr(1)=s;arr}
    makarr: [TT](f: TT, s: TT)(implicit evidence$1: Manifest[TT])Array[TT]

    scala> makarr(100,20)
    res171: Array[Int] = Array(100, 20)

    scala> makarr("ddd",20)
    res172: Array[Any] = Array(ddd, 20)

    scala> makarr[String]("ddd","dd")
    res176: Array[String] = Array(ddd, dd)

    多重界定

    类型变量可以同时有上界和下界,写法如下:

    T<:Upper>:Lower

    可以多个视图界定

    T<%Compareable[T]<%String

    可以多个上下文界定

    T :Ordering:Manifest

    类型约束

     类型约束提供给你的是另一种限定类型的方式,总共有三种方式可供使用:

    T=:=U   //T是否等于U

    T<:<U  //T是否为U的子类型

    T<%<U //T是否被视图(隐式)转换为U

    这些约束并非内建在语言当中,他们是scala类库提供的特性。

    scala> class pair[AA](val f:AA,val s:AA){ def smaller(implicit ord: AA<:<Ordered[AA])={ if (f.compareTo(s)<0) f else s;}}
    defined class pair

    scala> val p2=new pair("af","dd")
    p2: pair[String] = pair@2b149f0a

    scala> val p2=new pair[String]("af","dd")
    p2: pair[String] = pair@4fc7a2d2

     你可以构造出pair[File]对象,尽管File不是带先后次序的,只有调用smaller的时候才会报错

    scala> p2.smaller
    <console>:19: error: Cannot prove that String <:< Ordered[String].
    p2.smaller
    ^

    Option类的orNull方法,orNull的实现带有约束Null<:<A

    scala> val fruits=Map((1,"apple"),(2,"orange"),(3,"banana"))
    fruits: scala.collection.immutable.Map[Int,String] = Map(1 -> apple, 2 -> orange, 3 -> banana)

    scala> fruits.get(2)
    res219: Option[String] = Some(orange)

    scala> fruits.getOrElse(2,0)
    res220: Any = orange

    scala> fruits.getOrElse(100,0)
    res221: Any = 0

    scala> fruits.get(50)
    res222: Option[String] = None

    scala> val f1=fruits.get(2)
    f1: Option[String] = Some(orange)

     //final def orNull[A1 >: String](implicit ev: Null <:< A1): A1

    scala> f1.orNull
    res225: String = orange

    scala> val f1=fruits.get(5)
    f1: Option[String] = None

    scala> f1.orNull
    res236: String = null

    型变 

    函数如下

    def makfrends(p:Pair[Person])

    Student是Person的子类,但我们不能用Pair[Student]作为参数调用makfrends,因为Pair[Student] 和Pair[Person] 没有任何关系

    如果想要有关系,Pair类的声明应该如下:

    class Pair[+T](val f:T;val s:T)

    +T 意味着该类型是T类型协变的,也就是说,它与T按同样的方向形变

    Student是Person的子类型,Pair[Student] 也就是Pair[Person]的子类型了

    另一个方向的型变 就是[-T],就是逆变了

     swap [swɑp] 交换

    定义一个不可变类Pair[T,S], 带一个swap方法,返回组件交换过位置的新对偶。

    scala> class pair[T,S](first:T,second:S){def swap()={new pair[S,T](second,first)}}
    defined class pair

    scala> val p1=new pair("100",5)
    p1: pair[String,Int] = pair@15fe6b60

    scala> val p2=p1.swap()
    p2: pair[Int,String] = pair@3a32539


    scala> val p1=new pair(100,"dage")
    p1: pair[Int,String] = pair@314ba847

    scala> val p2=p1.swap()
    p2: pair[String,Int] = pair@46007b16

    定义一个可变类Pair[T],带一个swap方法,交换对偶中组件的位置。

    scala> class pair[T](var f:T,var s:T){def swap(){ val tmp=f;f=s;s=tmp;println("f:"+f+";s:"+s)};}
    defined class pair

    scala> val p1=new pair(100,50)
    p1: pair[Int] = pair@5120a555

    scala> p1.swap
    f:50;s:100

     给定类Pair[T, S] ,编写一个泛型方法swap,接受对偶作为参数并返回组件交换过位置的新对偶。 

    scala> class pair[T,S](val first:T,val second:S){ def tostring{ println("f:"+first+";s:"+second)}}
    defined class pair

    scala> def swap[T,S](p:pair[T,S])={new pair(p.second,p.first)}
    swap: [T, S](p: pair[T,S])pair[S,T]

    scala> val mm=new pair("dd",84)
    mm: pair[String,Int] = pair@785311b4

    scala> swap(mm)
    res58: pair[Int,String] = pair@7e282649

    scala> swap(mm).first
    res59: Int = 84

    快学scala   17章例四

    scala> class Pair[T](val first: T, val second: T) { def replaceFirst(newFirst: T) = new Pair[T](newFirst, second);override def toString = "(" + first + ", " + second + ")";

    def replaceFirst2[R >: T](newFirst: R) = new Pair[R](newFirst, second);}
    defined class Pair

    scala> class Person(val name: String, val age: Int){override def toString = name + " " + age}
    defined class Person

    scala> class Student(val school: String, name: String, age: Int) extends Person(name, age){override def toString = super.toString + " " + school}
    defined class Student

    scala> val p1 = new Pair(new Person("tianyongtao", 98), new Person("xiaoma", 56))
    p1: Pair[Person] = (tianyongtao 98, xiaoma 56)

    scala> val p2 = p1.replaceFirst(new Student("beida", "liu", 101))  //newfirst:Student可以转化成Person(子->父)

    p2: Pair[Person] = (liu 101 beida, xiaoma 56)

    scala> val p3 = new Pair(new Student("skd", "gang", 81), new Student("shenda", "gggg", 25))
    p3: Pair[Student] = (gang 81 skd, gggg 25 shenda)

    scala> val p4 = p1.replaceFirst2(new Person("li", 77)) //replaceFirst2函数预定义了新的类型变量下界,second:student转化为Person(子->父)
    p4: Pair[Person] = (li 77, xiaoma 56)

    scala> val p4 = p3.replaceFirst2(new Person("li", 77))//replaceFirst2函数预定义了新的类型变量下界,second:student转化为Person(子->父)
    p4: Pair[Person] = (li 77, gggg 25 shenda)

    scala> val p4 = p3.replaceFirst(new Person("li", 77)) //newFirst:Person无法转化为Student(父->子)
    <console>:13: error: type mismatch;
    found : Person
    required: Student
    val p4 = p3.replaceFirst(new Person("li", 77))
    ^

    经验证为发现RichInt,应该是BigInt,BigInt的存在丰富了Int,Int可以自动转换为BigInt

    使用视图定界可以将Comparable[Int]转化为Comparable[BigInt]

    scala> def middle[T](iter:Iterable[T]):T={ val ls=iter.toList;ls(ls.size/2) }
    middle: [T](iter: Iterable[T])T

    scala> middle("world")
    res12: Char = r

  • 相关阅读:
    网络管理不得不知道的一些常识
    DWZ(一):框架初了解
    第三天 ThinkPHP手把手高速拼接站点(三)
    stl之list双向链表容器应用基础
    如何使用ninja编译系统编译我们的程序?
    由抓取豆瓣信息想到的網絡知識
    学习实践:使用模式,原则实现一个C++数据库訪问类
    加入新的linux系统调用
    【转】repo 的一些用法和理解-不错
    【转】ubuntu 12.04 LTS将关闭最大化最小化移动到右上角
  • 原文地址:https://www.cnblogs.com/playforever/p/8022739.html
Copyright © 2011-2022 走看看