zoukankan      html  css  js  c++  java
  • Scala 入门笔记

    [T <: A] UpperBound 上界:T的上界是A类型,即T的父类是A类型

    abstract class Animal {
    def name: String
    }

    abstract class Pet extends Animal {}

    class Cat extends Pet {
    override def name: String = "Cat"
    }

    class Dog extends Pet {
    override def name: String = "Dog"
    }

    class Lion extends Animal {
    override def name: String = "Lion"
    }

    class UpperBoundDemo2[P <: Pet](p: P) {
    def pet: P = p
    }

    object UpperBoundDemo2 {
    def main(args: Array[String]): Unit = {
    val dogContainer = new UpperBoundDemo2[Dog](new Dog)
    val catContainer = new UpperBoundDemo2[Cat](new Cat)

    println(dogContainer.pet.name)

    // 这行编译会报错,因为UpperBoundDemo2 要求 P 必须是 Pet的子类,而Lion是继承于Animal的
    val lionContainer = new UpperBoundDemo2[Lion](new Lion)
    }
    }

      

    [B >: A] LowerBound 下界:B类是的子类是A

    trait Node[+B] {
      // 因为函数的参数是逆变,返回是协变,所以此处需要用到下界,来传入B的父类U,满足逆变
      def prepend[U >: B](elem: U): Node[U]
    }
    
    case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
      override def prepend[U >: B](elem: U): Node[U] = ListNode(elem, this)
      def head: B = h
      def tail: Node[B] = t
    }
    
    case class Nil[+B]() extends Node[B] {
      override def prepend[U >: B](elem: U): Node[U] = ListNode(elem, this)
    }
    
    object LowerBoundClass extends App {
      trait Bird
      case class AffricanSwallow() extends Bird
      case class EuropeanSwallow() extends Bird
    
      val affricanSwallowList =  ListNode[AffricanSwallow](AffricanSwallow(), Nil())
      val birdList: Node[Bird] = affricanSwallowList
    
      birdList.prepend(new EuropeanSwallow)
    
    
    }
    

      

    [B <% A] ViewBound 表示B类型需要转换成A类型,需要一个隐式转换函数

    [B : A] ContextBound 需要一个隐式转换的值

      [-A] 逆变, 作为参数类型,如果A是T的子类,那么C[T]是C[A]的子类

      

    abstract class Printer[-A] {
      def print(value: A): Unit
    }
    
    class AnimalPrinter extends Printer[AnimalC] {
      override def print(value: AnimalC): Unit = {
        println("This Animal's name is: " + value.name)
      }
    }
    
    class CatPrinter extends Printer[CatC] {
      override def print(value: CatC): Unit = {
        println("This Cat's name is: " + value.name)
      }
    }
    
    object ContravarianceTest extends App {
      val myCat: CatC = CatC("Tom")
    
      def printMyCat(printer: Printer[CatC]): Unit = {
        printer.print(myCat)
      }
    
      val catPrinter: Printer[CatC] = new CatPrinter
      val animalPrinter: Printer[AnimalC] = new AnimalPrinter
    
      // Printer[AnimalC] 可以替换 Printer[CatC] 而反过来不可以
      printMyCat(catPrinter)
      printMyCat(animalPrinter)
    }
    

      

      [+B] 协变,作为返回类型,如果B是T的子类,那么C[B]是C[T]的子类

    如下面例子,cat、dog都是Animal的子类,Scala标准库中有 sealed abstract class List[+A],所以List[cat], list[dog]都可以替换

    List[Animal]的位置,因为cat、dog都是Animal的子类

    abstract class AnimalC {
      def name: String
    }
    
    case class CatC(name: String) extends AnimalC
    case class DogC(name: String) extends AnimalC
    
    class CovarianceTest {
    
    }
    
    object CovarianceTest extends App {
      def printAnimalName(animals: List[AnimalC]): Unit = {
        animals.foreach(animal => println(animal.name))
      }
    
      val cats: List[CatC] = List(CatC("Tom"), CatC("Jack"))
      val dogs: List[DogC] = List(DogC("Nill"), DogC("Jim"))
    
      printAnimalName(cats)
      printAnimalName(dogs)
    }
    

      

  • 相关阅读:
    mysql新建用户的方法
    工具网站
    如何做好站内锚文本?
    js 创建对象与继承
    js tips
    js作用域链 js没有块级作用域
    css
    instanceof
    问题
    传递,引用副本传递
  • 原文地址:https://www.cnblogs.com/sunnystone85/p/11371417.html
Copyright © 2011-2022 走看看