scala学习笔记1-泛型、界定、形变、this.type、复合类型、抽象类型

2024-02-10 07:48

本文主要是介绍scala学习笔记1-泛型、界定、形变、this.type、复合类型、抽象类型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、 Scala中的泛型
class Triple[F: ClassTag, S : ClassTag, T : ClassTag](val f : F, val s : S, val t :T)  <span style="font-family: Arial, Helvetica, sans-serif;">//其中,ClassTag在scala.reflect.ClassTag中,并且ClassTag是隐式的,可省略;</span>
val t1 = new Triple("hadoop", "spark", "bigdata");
val t2 = new Triple[String, Int, Double]("bigdata", 1, 1.0);


二、Scala中Bounds(界定)

    一般的Bounds

    <: 使得T必须是Comparable[T]的子类,这T类型的a,b才有compareTo方法。

class Pair[T <: Comparable[T]](val a : T, val b : T)
if(a.compareTo(b)> 0) a else b

    View Bounds(视图界定)

class Pair2 [T <% Comparable[T]](val a : T, val b :T)
<% 使得T不是Comparable[T]的子类型,隐式转为它的子类。比如传入的是Int类型,Int类型没有实现Comparable[T]。故先要将Int隐式转为RichInt,此时RichInt是Comparable[T]的子类
class Pair3 [T <% Ordered[T]](val a : T, val b : T)
转为Ordered[T],可以将对象以a > b 的形式进行比较。If(a>b) a else b,其实>是a的方法

    Context Bounds

class Pair_Ordering [T : Ordering : ClassTag](val a : T, val b : T) {def bigger(implicit ordered : Ordering[T]) ={if(ordered.compare(a, b) > 0) a else b}
}
T :Ordering表示存在一个隐式值为Ordering[T]

     Manifest、classManifest、ClassTag、TypeTag

      利用Manifest可以创建泛型数组。Manifest中存储了T的实际类型的信息,在实际运行中作为参数运行在上下文环境中。其中T:Manifest和上文的T:Ordering都属于Context Bounds的用法

def arrayMake[T : Manifest](a : T, b : T) = {val array = new Array[T](2);array(0) = a;array(1) = b;array;
}

         后来,Manifest和classManifest分别被TypeTag和ClassTag所取代。ClassType的限定要弱于TypeTag。ClassType提供了运行时的类型信息,而TypeTag提供了所有的静态类型信息。而实际中,ClassType提供的运行时类型信息已经足够使用,因此在spark等中使用广泛。

           def arrayMake2[T : ClassTag](elems : T*) = Array[T](elems : _*)

            ,这里可以看到T:ClassTag,自动隐式转为ClassTag[T]

            arrayMake2(1,2).foreach(println)

           主要是在运行时指定在编译时无法确定的比较高级别的类别的信息,不包括static级别的type信息。

    多重界定

          T <:A with B 表示T是AB的子类。

          T : A: B 是上下文界定。表示必须同时存在A[T]和B[T]的隐式值。

          T <% A <% B 是视图界定,表示T可以隐式转为AB。

          T>: A <: B 表示A是T的下界,B是T的上界。并且,下界A必须写在上界B的前面,同时A一定是B的子类。

三、 Scala的类型约束

     A =:=B 表示A类型等同B类型

     A<:< B 表示A类型是B类的子类型

四、 Scala中的Variance

    Variance称为形变 T

       协变 +T

       逆变 –T

       class  Person[+T](first : T, second : T) 则后面的first和second的类型必须是T的父类。-T的话,表示first和second的类型必须是T的子类。

五、 Scala中的链式调用

     任何的类对象都有type属性:this.type

class Animal {def breathe() : this.type = {//TODOthis}
}class Dog extends Animal {def eat() : this.type = {//TODOthis}
}
Val dog = new Dog; dog.breathe().eat();

六、 Scala中的路径依赖

    内部类享有外部类的实例,可以访问外面类中的私有成员;而外部类不可以访问内部类中的私有成员。

    Scala中内部类必须依赖于外部类的实例。外部类实例不同,则内部类也不同,依赖于外部类,称为路径依赖,不同路径下的内部类,类型不同。

class Outter {private[this] val x = 1class Inner {private[this] val y = x + 1}
}object PathDependencies extends App {val out1 = new Outterval out2 = new Outter//out1.Inner和out2.Inner在不同路径下,类型不同val inner1 : out1.Inner = new out1.Innerval inner2 : out2.Inner = new out2.Inner//类型投影,out1.Inner,out2.Inner是Outter#Inner的子类val inner3 : Outter#Inner = new out1.Innerval inner4 : Outter#Inner = new out2.Inner
}

七、 Scala中的结构体类型

//传入实现get方法的匿名类实例
init(new {def get() = println("geted")})//申明一个含有get方法的类型,类型于c语言中的结构体类型
type X = {//不需要像java那样,通过接口和实现接口来限制def get() : Unit
}
def init1(res : X) = {res.get
}
init1(new {def get() = println("geted again")})
object A {def get() = println("geted In A")}
init1(A)

八、 Scala中的复合类型

trait A //接口A
trait B //接口B
class C extends A with B {//继承A,B,实现get的Cdef get() = println("hello compoundtype!")
}object CompoundType {//复合类型,该类型表示既是A又是B,同时还要实现get方法type CompoundType = A with B {def get():Unit}def init(x : CompoundType)  = {x.get()}def main(args: Array[String]): Unit = {init(new C)}
}

九、 Scala中的InfixType

object InfixType {def main(args: Array[String]): Unit = {//右结合的表达式"Spark" >>: "Hadoop">>: Logval list = List()val newList = 1 :: 2 :: listprintln(newList)class Infix_Type[A, B]val it : Infix_Type[Int, String] =nullval it1 : Int Infix_Type String =nullval cons =Constant("1", "2")cons match {case "1" Constant "2"=> {println("spark!")} }}
}
case class Constant(first : String, second : String)object Log {def >>: (data : String) : Log.type = { // >>: 这是方法名println(data);Log}
}

 

十、Self Types

      自类型, 相当于对当前实例关键this起一个别名。用法如下://有点类似于javascript中的var self = this; 的用法

Class Outter {self =>val iClass Inner {def foo(){ println(self.i) }}
}

      主要用途在对this的一种限定,必须要混入另一个类型。用法如下:

trait S1
class S2 {this:S1=>
}
val s = new S2 with S1  //实例化S2的时候需要with S1
class S3 extends S2 with S1  //extends S2的时候需要 with S1

十一、 Scala中的依赖注入

      通过self type的用法,实现依赖组件的注入

object DependenceInjection extends App {T.authorize()
}
trait Logger{def log(msg:String)
}
class Auth{auth : Logger => //关键点val key = "hello di"def authorize() = {log(key)//TODO}
}//T对象继承Auth则必须with Logger实现log方法
object T extends Auth with Logger {override def log(msg:String) = {println(msg)}
}

十二、 Scala中的抽象类型AbstractType

     抽象类通过type声明类型,但不指定具体的类型

     在子类中指定相关类型,和实现抽象类中的方法

trait Reader {type input <: java.io.Serializable //input 必须是Serializable的子类type resultsdef read(str : input) : results
}              class FileReader extends Reader {type input = Stringtype results = BufferedSourceoverride def read(str : input):results = {Source.fromFile(str)}
}

这篇关于scala学习笔记1-泛型、界定、形变、this.type、复合类型、抽象类型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/696538

相关文章

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

Go语言利用泛型封装常见的Map操作

《Go语言利用泛型封装常见的Map操作》Go语言在1.18版本中引入了泛型,这是Go语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性,本文将通过泛型实现封装常见的Map操作,感... 目录什么是泛型泛型解决了什么问题Go泛型基于泛型的常见Map操作代码合集总结什么是泛型泛型是一种编程范式,允

解决Spring运行时报错:Consider defining a bean of type ‘xxx.xxx.xxx.Xxx‘ in your configuration

《解决Spring运行时报错:Considerdefiningabeanoftype‘xxx.xxx.xxx.Xxx‘inyourconfiguration》该文章主要讲述了在使用S... 目录问题分析解决方案总结问题Description:Parameter 0 of constructor in x

Redis的Zset类型及相关命令详细讲解

《Redis的Zset类型及相关命令详细讲解》:本文主要介绍Redis的Zset类型及相关命令的相关资料,有序集合Zset是一种Redis数据结构,它类似于集合Set,但每个元素都有一个关联的分数... 目录Zset简介ZADDZCARDZCOUNTZRANGEZREVRANGEZRANGEBYSCOREZ

IDEA如何将String类型转json格式

《IDEA如何将String类型转json格式》在Java中,字符串字面量中的转义字符会被自动转换,但通过网络获取的字符串可能不会自动转换,为了解决IDEA无法识别JSON字符串的问题,可以在本地对字... 目录问题描述问题原因解决方案总结问题描述最近做项目需要使用Ai生成json,可生成String类型

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

Python中异常类型ValueError使用方法与场景

《Python中异常类型ValueError使用方法与场景》:本文主要介绍Python中的ValueError异常类型,它在处理不合适的值时抛出,并提供如何有效使用ValueError的建议,文中... 目录前言什么是 ValueError?什么时候会用到 ValueError?场景 1: 转换数据类型场景