• Scala 泛型类型和方法


    abstract class Stack[A] { 
      def push(x: A): Stack[A] = new NonEmptyStack[A](x, this) 
        def isEmpty: Boolean 
        def top: A 
        def pop: Stack[A] 
        val contents: T = _   //初始值:_ ,表示一个默认值,数字类型是0 ,boolean是false ,Unit是() (无参数无返回),其他是null
    } 
    class EmptyStack[A] extends Stack[A] { 
      def isEmpty = true
      def top = error("EmptyStack.top") 
      def pop = error("EmptyStack.pop") 
    } 
    class NonEmptyStack[A](elem: A, rest: Stack[A]) extends Stack[A] { 
      def isEmpty = false
      def top = elem 
      def pop = rest 
    } 
      
    val x = new EmptyStack[Int] 
    val y = x.push(1).push(2) 
    println(y.pop.top) 
      
    def isPrefix[A](p: Stack[A], s: Stack[A]): Boolean = { 
      p.isEmpty || 
      p.top == s.top && isPrefix[A](p.pop, s.pop) 
    } 
      
    val s1 = new EmptyStack[String].push("abc") 
    val s2 = new EmptyStack[String].push("abx").push(s1.top) 
    println(isPrefix[String](s1, s2)) 
    

    类型参数边界

      在用类型参数定义了一个抽象类Set[A]后,在实现中要用到比较(<>),但是不能确定A的具体类型,因此不能直接使用。一个解决办法就是对合法类型进行限制,对只含有方法<>的类型放行。在标准库里有一个特质Ordered[A],用来表示可比较的类型。现在可以强制要求这个类型为Ordered的子类型。可以通过给出一个上界(upper bound)的方式来解决这个问题:

    abstract class Set[A] {
      def incl(x: A): Set[A]
      def contains(x: A): Boolean
    }
    
    // 传入的A类型参数必须是Ordered[A]的子类型
    class EmptySet[A <: Ordered[A]] extends Set[A] {
    	def contains(x: A): Boolean = false
    	def incl(x: A): Set[A] = new NonEmptySet(x, new EmptySet[A], new EmptySet[A])
    	// 在new NonEmptySet(...)时,没有写入类型参数。因为可以从返回值类型中推断出来。
    }
    class NonEmptySet[A <: Ordered[A]](elem: A, left: Set[A], right: Set[A]) extends Set[A] {
    	def contains(x: A): Boolean =
    		if (x < elem) left contains x
    		else if (x > elem) right contains x
    		else true
    	def incl(x: A): Set[A] =
    		if (x < elem) new NonEmptySet(elem, left incl x, right)
    		else if (x > elem) new NonEmptySet(elem, left, right incl x)
    		else this
    }
    
    // 先创建一个Ordered的子类
    case class Num(value: Double) extends Ordered[Num] {
    	def compare(that: Num): Int =
    		if (this.value < that.value) -1
    		else if (this.value > that.value) 1
    		else 0
    }
    
    val s = new EmptySet[Num].incl(Num(1.0)).incl(Num(2.0))
    s.contains(Num(1.5))
    

    变化型注解(variance annotation)

    “+”表示协变,“-”表示逆变。
    C[+T]:如果A是B的子类,那么C[A]是C[B]的子类。
    C[-T]:如果A是B的子类,那么C[B]是C[A]的子类。
    C[T]:无论A和B是什么关系,C[A]和C[B]没有从属关系。

    协变类型应该出现在协变位置,这些位置包括:类里值的参数类型;方法的返回值类型;以及其他协变类型中的参数。放在其他地方会被拒绝

    class Array[+A] {
    	def apply(index: Int): A
    	def update(index: Int, elem: A)  // 可以通过下界(lower bounds)来解决这个问题
    								^ covariant type parameter A
    								  appears in contravariant position.
    }
    
    // 下界(Lower Bounds)
    // B是A的父类
    class Stack[+A] {
    	def push[B >: A](x: B): Stack[B] = new NonEmptyStack(x, this)
    }
    
  • 相关阅读:
    Redis Cluster笔记
    http协议之 COOKIE
    lor框架代码分析
    PHP--SPL扩展学习笔记
    lua协程----ngx-lua线程学习笔记
    设计模式
    eclipse中使用maven创建springMVC项目
    一般处理程序里使用session对象
    .Dot NET Cored简介
    Spring 依赖注入(基本注入和自动适配注入)
  • 原文地址:https://www.cnblogs.com/wwxbi/p/4176215.html
Copyright © 2020-2023  润新知