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)
}

Scala 泛型类型和方法的更多相关文章

  1. Scala 深入浅出实战经典 第42讲:scala 泛型类,泛型函数,泛型在spark中的广泛应用

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  2. scala的apply方法

    package com.test.scala.test /** * apply 方法 */ object ApplyTest { def main(args: Array[String]): Unit ...

  3. “T”必须是具有公共的无参数构造函数的非抽象类型,才能用作泛型类型或方法

    最近在项目中,使用EF编程时,在使用泛型类型的过程中,写了一上午,结果生成时,编译不通过,报出如下错误: “T”必须是具有公共的无参数构造函数的非抽象类型,才能用作泛型类型或方法.如图: 找了好久,终 ...

  4. spark-shell的Scala的一些方法详解

    Tom,DataBase,80 Tom,Algorithm,50 Tom,DataStructure,60 Jim,DataBase,90 Jim,Algorithm,60 Jim,DataStruc ...

  5. scala 基本类型和操作

    Scala基本类型 Scala中的基本数据类型如下图:  (来源:Programming in scala) 从上表中可以看出,Scala的基本数据类型与Java中的基本数据类型是一一对应的,不同的是 ...

  6. 第1节 Scala基础语法:scala中的方法源码分析

    val list=List(1,2,3,4) list.reduce((x:Int,y:Int)=>x+y)--->list.reduceLeft((x:Int,y:Int)=>x+ ...

  7. scala函数和方法的差别

    想知道什么差别,把代码复制下来运行看结果 // 1 1 2 3 5 8 13 def f(x:Int) :Int= { ) ) else f(x-)+f(x-) } println(f()) // v ...

  8. 大数据学习——scala函数与方法

    package com /** * Created by Administrator on 2019/4/8. */ object TestMap { def ttt(f: Int => Int ...

  9. java 声明多个泛型类型和通配符

    若一个类中多个字段需要不同的泛型声明,则在声明类的时候指定多个泛型类型即可: 格式: public interface IDAO<PK, T> { PK add(T t); void re ...

随机推荐

  1. Qt 线程基础(QThread、QtConcurrent等)

    [-] 使用线程 何时使用其他技术替代线程 应该使用 Qt 线程的哪种技术 Qt线程基础 QObject与线程 使用互斥量保护数据的完整 使用事件循环防止数据破坏 处理异步执行 昨晚看Qt的Manua ...

  2. 第二百九十六节,python操作redis缓存-Hash哈希类型,可以理解为字典类型

    第二百九十六节,python操作redis缓存-Hash哈希类型,可以理解为字典类型 Hash操作,redis中Hash在内存中的存储格式如下图: hset(name, key, value)name ...

  3. vector、map删除当前记录

    map<string, string> sMap; map<string, string>::iterator iter; for(iter = sMap.begin();it ...

  4. java---final、finally、finalize的区别

    Java finalize方法使用 标签: javaappletobjectwizardjvm工作 2011-08-21 11:37 48403人阅读 评论(5) 收藏 举报  分类: Java(96 ...

  5. 修改Java标准库源码

    以下是摘抄,实际操作没有测试   先前我曾提到,原本想借由“改动Java标准库源码”来测知Class object的生成,但由于其ctor原始设计为private,也就是说不可能透过这个管道生成Cla ...

  6. 转载:【原译】Erlang列表处理(Efficiency Guide)

    转自:http://www.cnblogs.com/futuredo/archive/2012/10/22/2734186.html List handling 1  Creating a list ...

  7. 基于bootstrap的select(可多选)

    如图:

  8. [转]五分钟看懂UML类图与类的关系详解

    在画类图的时候,理清类和类之间的关系是重点.类的关系有泛化(Generalization).实现(Realization).依赖(Dependency)和关联(Association).其中关联又分为 ...

  9. [mysql] Install/Remove of the Service Denied

    在windos 的cmd下安装mysql 在mysql的bin目录下面执行: mysqld --install 报错: 信息如下: Install/Remove of the Service Deni ...

  10. 从css样式表中抽取元素尺寸

    jS从样式表取值的函数.IE中以currentStyle,firefox中defaultView来获取 DOM.style仅仅能读到写在html中的样式值 获取样式值的函数 function retu ...