Scala 语言学习之泛型(7)
admin
2023-07-28 03:20:07
0次

==> 泛型类

        ---> T 可以代表任意类型

class Person[T]{
  private var name:T = _

  def setName(name:T) = {this.name = name}
  def getName():T = {this.name}
}

// ***********测试*****************
object Person{
  def main(args:Array[String]):Unit = {
    var p = new Person[String]()
    p.setName("hello")
    println(p.getName())
  }
}


==> 泛型函数

        ---> 类型参数放在方法名之后

//* 泛型函数
// 创建一个固定类型的数组
// 普通函数
def mkInt(elems:Int*) = Array[Int](elems:_*)
def mkString(str:String*) = "mkString"

// 使用泛型函数,可以接收任意类型
def mkArray[T:ClassTag](elems:T*) = Array[T](elems:_*)

// ***********测试*****************
// 普通函数只能传入相对应类型的参数
mkInt(1,2,3)
mkString("hello", "world")

// 泛型函数可以传入任意类型的参数
mkArray(11.26,665, 84, "hello")


==> 类型的上界和下界(Upper Bounds 和 Lower Bounds)

        ---> 用来定义泛型变量的范围 :  

        ---> S <: T  (上界)        S 必须是 T 类型的子类或类本身

class Person1{
  def gender() = {println("gender")}
}

class Man extends Person1{
  override def gender() = {println("man")}
}

class Women extends Person1{
  override def gender() = {println("women")}
object UpperBoundsAndLowerBounds {
  // 定义一个泛型函数,通过上界的方式指定泛型的范围必须是 Person1 的子类或者Person1 类,并调用类中的 gender 方法
  def getGender[T <: Person1](g:T) = {g.gender()}

  def main(args:Array[String]): Unit = {
    // 创建一个Person1 对象 ,调用getGender 方法调用 Personal 中的 gender 方法
    var p:Person1 = new Person1
    getGender(p)

    // 创建一个 Man 对象 ,通过 getGender 方法调用Man 类中的 gender 方法
    var m = new Man
    getGender(m)
  }

}


        ---> U >: T(下界)        U 必须是 T 类型的父类或类本身,此处不作示例,与上面例子类似,只是传入 getGender 方法中的参数必须是 Person1 类或其父类的对象


==> 视图界定    <%

        ---> 与类型的上界相似,但是比类型的上界适用范围更广,除了所有的子类与类本身,它还允许通过隐式转换得到的类型

def int2String[T <% String](x:T, y:T) = {
  println(x + "*****" + y)
}

// ***********测试*****************
int2String("hello", "world")
implicit def int2String1(n:Int):String = {n.toString}
int2String(100, 120)


==> 协变和逆变

        ---> 协变: 泛型变量的值可以是子类或类本身     在类型参数前加一个 “+” 符号    子类转换为父类

//* 协变和逆变   在类型的前面加入 +号,就可以使类的特征变为协变了
// 将子类对象转换为父类对象称为协变 +
// 将父类对象转换为子类对象称为逆变 -
package demo1{
  // 父类
  class Animal{}
  // 子类
  class Bird extends Animal
  class Sparrow extends Bird
  
  // 吃东西的类      协变
  class EatSomethings[+T](t:T){}

  // ***********测试*****************
  object Demo1{

    def main(args:Array[String]): Unit={
      // 创建一个吃东西的对象
      var c1:EatSomethings[Sparrow] = new EatSomethings[Sparrow](new Sparrow)

      var c2:EatSomethings[Animal] = c1
    }
  }
}


        ---> 逆变: 泛型变量的值可以是父类或类本身    在类型参数前加一个 “ - ” 符号    父类转换为子类    例:省略


==> 隐式转换函数    

        ---> 以关键字  implicit   申明

        ---> 单个参数

class Fruit(name:String){
  def getFruitName():String = {name}
}

class Monkey(f:Fruit){
  def say() = {println("Monkey like " + f.getFruitName()) }
}

// ***********测试*****************
object ImplicitDemo {
  def main(args:Array[String]):Unit = {
    var f:Fruit = new Fruit("bnanan")

    // 调用 fruit 的方法,希望 Monkey这个say 方法来实现
    // 需要将 fruit 的对象转换为 monkey 对象, 即定义一个隐匿转换函数
    implicit def fruit2Monkey(f:Fruit):Monkey = {new Monkey(f)}     // 将 fruit 对象转换为 Monkey 对象
    // 调用Monkey中的 say 方法
    f.say()
  }
}


==> 隐式参数    使用 implicit 关键字申明的函数参数

        ---> 可以使用隐式参数进行类型转换

// 隐式参数
def testParam(implicit name:String) = {println("The value is " + name)}
implicit val name:String = "这是一个隐式值"

// ***********测试*****************
testParam
//---------------------------------------------------------------

// 带隐式参数的泛型函数
// Ordered[T] 使类型可排序,
//     原型:def smaller
// (implicit order:T      =>    Ordered[T])
def smaller[T](a:T, b:T)(implicit order:T => Ordered[T]) = if(order(a) < b) a else b

// ***********测试*****************
smaller(100, 56)
smaller("hello", "hi")


==> 隐式类    对类  增加 implicit 限定 的类,其主要作用就是对类的功能增强

        ---> 编写一个隐式类,使类实现更多的功能

object testImplicit {

  // 定义一个隐式类
  implicit class Calc(x:Int){
    def add(a:Int):Int = a + x
  }

  // ***********测试*****************
  def main(args:Array[String]):Unit = {
    println("两个数字的和:" + 1.add(2))
  }
}

        ---> 程序过程分析:

                --- 当 1.add(2)时,scala 的编译器不会报错,在当前域中查找,有没有 implicit 修饰的,同时可以将 Int 作为参数的构造器,并且具有 add 方法的类,通过查找,找到 Calc

                --- 利用隐式类 Calc 来执行 add 方法


==> 个人总结:

        ---> 通过泛型,可以使我们定义一个模具,就像蛋糕的模具,我们可以分别放入草莓,蓝莓等不同的原料加工出不同口味的蛋糕来

        ---> 通过使用 上界,下界,视图界定,协变,逆变,对泛型的范围制定规则,使我们可以传入的符合规则的参数

        ---> 隐式函数,隐式参数,隐式类,会在程序运行时首先被查找,若有符合 以 implicit 修饰的参数,函数以及类,先执行,然后才运行程序


若总结有误,还请多多指教,谢谢!!!


相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...