Scala语言编码高级特性【下】

上篇:Scala语言编码高级特性【上】

Scala语言编码高级特性

1、泛型

案例1,代码实现:

package org.apache.scala.day07

/**
 * 时间: 2021/07/25 15:00
 * 描述: 泛型
 *
 * 泛型简单测试
 */
object Demo010_GenericType01 {

  def main(args: Array[String]): Unit = {

    println(new Student11[String, Int]("黄渤", 33).name)
    println(new Person11[String]("徐峥").name)

    val array = new Array[String](10)
    array(0) = "huangbo"
    //    array(1) = 11

  }
}

class Person11[T](var name: T) {}

class Student11[T, S](var name: T, var age: S) {}

打印输出:

案例2,代码实现:

package org.apache.scala.day07

class Person[T, S](var name: T, var age: S)

class Student(var name: String, var age: Int) extends Comparable[Student] {
  override def compareTo(o: Student): Int = {
    return o.age - this.age
  }
}

/**
 * 泛型类
 */
class MrRight1[T <: Comparable[T]] {
  //定义一个选择方法,实现选择的功能
  def choose(first: T, second: T): T = {
    if (first.compareTo(second) > 0) first else second
  }
}

/**
 * 泛型方法
 */
class MrRight2 {
  def choose[T <: Comparable[T]](first: T, second: T): T = {
    if (first.compareTo(second) > 0) first else second
  }
}

/**
 * 描述: 泛型的基本测试
 *
 * 泛型类 和 泛型方法的测试
 */
object Demo010_GenericType02 {

  def main(args: Array[String]): Unit = {

    println(new Person[String, Int]("黄渤", 33).name)

    // 如果是类上定义的泛型,通过下面的方式调用
    val right1 = new MrRight1[Student]
    val hadoop1 = new Student("java", 77)
    val spark1 = new Student("scala", 88)
    val student1 = right1.choose(hadoop1, spark1)
    println(student1.name)

    //如果是在方法上定义的泛型,可以使用下面的方式:
    var right2 = new MrRight2
    val hadoop2 = new Student("hadoop", 99)
    val spark2 = new Student("spark", 88)
    val student2: Student = right2.choose[Student](hadoop2, spark2)
    println(student2.name)
  }
}

打印输出:


2、类型界定 

代码实现:

package org.apache.scala.day07

/**
 * 描述: 类型界定
 */
class Demo011_GenericType02 {
  //  def compare[T](first:T,second:T)={
  def compare[T <: Comparable[T]](first: T, second: T) = {
    if (first.compareTo(second) > 0)
      first
    else
      second
  }
}

object Demo011_GenericType02 {

  def main(args: Array[String]): Unit = {

    val tvb = new Demo011_GenericType02
    println(tvb.compare("A", "B"))

  }
}

打印输出:


3、视图界定

代码实现:

package org.apache.scala.day07

/**
 * 视图界定
 */
case class Student1234[T, S <% Comparable[S]](var name: T, var height: S)

object GenericTypeTest3 {

  def main(args: Array[String]): Unit = {

    // 这是合法的语句
    val s = Student1234("john", "170")
    println(s.name, s.height)

    //下面这条语句不合法,这是因为Int类型没有实现Comparable接口
    //使用视图界定即可
    val s2 = Student1234("john", 170)
    println(s2.name, s2.height.isInstanceOf[Int])
  }
}

打印输出:


4、类型通配符 

代码实现:

package org.apache.scala.day07

class Person77(val name: String) {
  override def toString() = name
}

class Student77(name: String) extends Person77(name)

class Teacher77(name: String) extends Person77(name)

class Pair[T](val first: T, val second: T) {
  override def toString() = "first:" + first + "    second: " + second;
}

/**
 * 类型通配符
 */
object TypeWildcard {

  def main(args: Array[String]): Unit = {

    makeFriends(new Pair(new Student77("黄渤学生"), new Teacher77("徐峥老师")))
    makeFriends(new Pair(new Student77("黄渤学生"), new Student77("徐峥学生")))
    makeFriends(new Pair(new Teacher77("黄渤老师"), new Student77("徐峥学生")))
    makeFriends(new Pair(new Teacher77("黄渤老师"), new Teacher77("徐峥老师")))
  }

  // Pair的类型参数限定为[_<:Person],即输入的类为Person及其子类
  // 类型通配符和一般的泛型定义不一样,泛型在类定义时使用,而类型能配符号在使用类时使用
  def makeFriends(p: Pair[_ <: Person77]) = {
    println(p.first + " is making friend with " + p.second)
  }
}

打印输出:


5、上下界、视图边界实现方式 

代码实现:

package org.apache.scala.day07

class GranderFather

class Father extends GranderFather

class Me extends Father

class Son extends Me

class Tongzhuo

/**
 * 下界、视图边界实现方式
 */
object Demo013_GenericType_XiaJie {

  // 定义下界
  def getIDCard1[R >: Me](person: R): Unit = {
    println("好吧,他的身份证就交给你保管了");
  }

  // 定义上界
  def getIDCard2[R <: Me](person: R): Unit = {
    println("好吧,他的身份证就交给你保管了");
  }

  // 定义视图边界
  def getIDCard3[R <% Me](person: R): Unit = {
    println("好吧,他的身份证就交给你保管了");
  }

  def main(args: Array[String]): Unit = {

    getIDCard1[GranderFather](new GranderFather)
    getIDCard2[Son](new Son)
    getIDCard3[Me](new Me)

    // 这句代码会报错
    //    getIDCard[Tongzhuo](new Tongzhuo)

    implicit def tongzhuo2Me(tz: Tongzhuo): Me = new Me

    getIDCard3[Tongzhuo](new Tongzhuo)
  }
}

打印输出:


6、函数用泛型表示

将函数也用泛型表示,因为是协变的,输入的类型必须是T的超类,这样返回值类型 MyList[U] 就是 MyList[T] 的超类。符合协变的性质。

案例1,代码实现:

package org.apache.scala.day07

/**
 * 函数用泛型表示
 */
object XieBianTest {
  def main(args: Array[String]): Unit = {
    val list1: MyList[Any] = new MyList[AnyRef]("黄", null)
    val list2: MyList[Any] = new MyList[String]("黄", new MyList[String]("黄", null))

    val list3: MyList[String] = new MyList[String]("黄", null)
    val list4: MyList[Any] = new MyList[Object]("黄", list3)

    val abc: Any = "huangbo"
    list1.prepend[Any]("huangbo")
    println(list1)

  }
}

class MyList[+T](val head: T, val tail: MyList[T]) {
  /**
   * 将函数也用泛型表示
   * 因为是协变的,输入的类型必须是T的超类
   * 这样返回值类型 MyList[U] 就是 MyList[T] 的超类。符合协变的性质
   */
  def prepend[U >: T](newHead: U): MyList[U] = new MyList(newHead, this)

  //  def prepend[T](newHead: T): MyList[T] = new MyList(newHead, this)
}

打印输出:

 

 案例2,代码实现:

package org.apache.scala.day07

object XieBianTest2 {

  def main(args: Array[String]): Unit = {

    val list: List[Any] = new List[String]("光环国际", null)
    println(list)

  }
}

class List[+T](val head: T, val tail: List[T]) {

  def prepend[U >: T](newHead: U): List[U] = new List(newHead, this)

  override def toString = "" + head
}




打印输出:


7、逆变测试 

原因:对于Person3[Any] 和 Person3[String] 这两个父子类型来说

def test(x:Any){}
def test(x:String){}

由于+A协变,所以Person3[Any]是Person3[String]的父类,因此

val pAny = new Person3[AnyRef]
val pString = new Person3[String]
pAny.test(123) 合法
pAny = pString 合法
但是, pAny.test(123) 不合法

代码实现:

package org.apache.scala.day07
/**
 * 逆变测试
 */
object NibianTest {

  def main(args: Array[String]): Unit = {

  }
}

//声明逆变,不报错
class Person2[-A] {
  def test(x: A) {}
}

//声明协变,但会报错
/*class Person3[+A] {
  def test(x: A) {}
}*/

class Person4[+A] {
  def test[R >: A](x: R) {}
}

在Scala中,我们知道T是泛型,不确定是什么类型,所以不能确定T类型中,是否一定包含compareTo方法, 所以编译报错。

  Comparable 接口    compareTo

 T <: Comparable[T]  语法结构:

     表示将来传入进行的泛型的类型:T 必须是Comparable继承体系中的任何一员
     T <: Comparable[T]    只认T是Comparable的子类
     T <% Comparable[T]     除了会认识子类之外,还认识由其他的类隐式转换够来的类

  • 如果要从集合中读取类型T的数据,并且不能写入:
可以使用 ? extends 通配符;(Producer Extends)
  • 如果要从集合中写入类型T的数据,并且不需要读取
可以使用 ? super 通配符;(Consumer Super)
  • 如果既要存又要取
那么就不要使用任何通配符

代码实现:

package org.apache.java.day04;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class GenericTypeTest5 {

    public static void main(String[] args) {

        // 带有extends子类型限定的通配符可以向泛型对象读取。
        List<? extends Season> seasonList = new LinkedList<>();
//        seasonList.add(new Spring());
//        seasonList.add(new Summer());
        Season season = seasonList.get(0);
        Spring spring = (Spring) seasonList.get(1);

        // 带有super超类型限定的通配符可以向泛型对象中写入
        List<? super D> seasonList2 = new ArrayList<>();
//        seasonList2.add(new A());
//        seasonList2.add(new B());
//        seasonList2.add(new C());
    }
}

class A {
}

class B extends A {
}

class C extends B {
}

class D extends C {
}

class Season {
}

class Spring extends Season {
}

class Summer extends Season {

}

class Demo<E> {
    public void extendsTest(List<? extends E> list) {
        System.out.println("extendsTest ok");
    }

    public void superTest(List<? super E> list) {
        System.out.println("superTest ok");
    }
}

打印输出:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值