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)
}
Scala 泛型类型和方法的更多相关文章
- Scala 深入浅出实战经典 第42讲:scala 泛型类,泛型函数,泛型在spark中的广泛应用
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- scala的apply方法
package com.test.scala.test /** * apply 方法 */ object ApplyTest { def main(args: Array[String]): Unit ...
- “T”必须是具有公共的无参数构造函数的非抽象类型,才能用作泛型类型或方法
最近在项目中,使用EF编程时,在使用泛型类型的过程中,写了一上午,结果生成时,编译不通过,报出如下错误: “T”必须是具有公共的无参数构造函数的非抽象类型,才能用作泛型类型或方法.如图: 找了好久,终 ...
- spark-shell的Scala的一些方法详解
Tom,DataBase,80 Tom,Algorithm,50 Tom,DataStructure,60 Jim,DataBase,90 Jim,Algorithm,60 Jim,DataStruc ...
- scala 基本类型和操作
Scala基本类型 Scala中的基本数据类型如下图: (来源:Programming in scala) 从上表中可以看出,Scala的基本数据类型与Java中的基本数据类型是一一对应的,不同的是 ...
- 第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+ ...
- scala函数和方法的差别
想知道什么差别,把代码复制下来运行看结果 // 1 1 2 3 5 8 13 def f(x:Int) :Int= { ) ) else f(x-)+f(x-) } println(f()) // v ...
- 大数据学习——scala函数与方法
package com /** * Created by Administrator on 2019/4/8. */ object TestMap { def ttt(f: Int => Int ...
- java 声明多个泛型类型和通配符
若一个类中多个字段需要不同的泛型声明,则在声明类的时候指定多个泛型类型即可: 格式: public interface IDAO<PK, T> { PK add(T t); void re ...
随机推荐
- Qt 事件处理的五个层次
看了这篇文章(见http://devbean.blog.51cto.com/448512/231861),然后经过自己的思考,把Qt事件处理的五个层次.同时也是Qt时间处理的流程画了出来.若有不对请批 ...
- 关于Cocos2d-x中打包图集和使用方法
准备的过程 1.打开TextruePacker软件 2.把游戏中要使用的图片拖到TextruePacker里面,TextruePacker会自动帮我们排序,让所有小图变成一个大图 3.点击Publis ...
- 【转】7Z命令行解压缩
7z.exe在CMD窗口的使用说明如下: 7-Zip (A) 4.57 Copyright (c) 1999-2007 Igor Pavlov 2007-12-06 Usage: 7za <co ...
- Android Activity 传递数据
activity中数据的传递方式有2中,一种是使用putExtra()传递,另外一种是传递Bundle对象,使用putExtras()方法. 方法一 发送数据 putExtra()传送的是键值对,第一 ...
- 优矿众包对冲基金计划”优选策略---100w实盘资金管理权!!
https://uqer.io/contest/ http://www.cnblogs.com/dunitian/p/4939369.html 优连
- php Laravel 框架之建立后台目录
今天研究了在Laravel框架中的控制器中加入后台的目录.发现了一些小的规律,拿来和大家分享一下吧. 通常情况下,我们是直接在controllers目录中加入我们的控制器,然后再routes.php ...
- fatal error: malformed or corrupted AST file: 'Unable to load module Darwin.pcm 问题解决
xcode5 编译project.偶然碰到了以下的问题: fatal error: malformed or corrupted AST file: 'Unable to load module &q ...
- R 中的do.call 函数
do.call 函数是一个高阶函数, 其第一个参数为一个函数名,或者匿名函数,第二个参数是一个list 对象, 其实是参数列表 比如读取文件test.txt, 内容为 read.table(input ...
- CentOS和Ubuntu安装软件命令对比(区别)
此表内容来自<Ubuntu Server最佳方案>,CentOS和Ubuntu(Debian)是VPS最常见的系统,这份表很实用,分享下
- CentOS Linux 下安装Samba
一.Samba简介: Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成.Linux中搭建环境有几个需要使用的软件包: (1)samba-client:这个 ...