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中Json和其他类型相互转换的实现示例

《Python中Json和其他类型相互转换的实现示例》本文介绍了在Python中使用json模块实现json数据与dict、object之间的高效转换,包括loads(),load(),dumps()... 项目中经常会用到json格式转为object对象、dict字典格式等。在此做个记录,方便后续用到该方

python中的显式声明类型参数使用方式

《python中的显式声明类型参数使用方式》文章探讨了Python3.10+版本中类型注解的使用,指出FastAPI官方示例强调显式声明参数类型,通过|操作符替代Union/Optional,可提升代... 目录背景python函数显式声明的类型汇总基本类型集合类型Optional and Union(py

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

Python学习笔记之getattr和hasattr用法示例详解

《Python学习笔记之getattr和hasattr用法示例详解》在Python中,hasattr()、getattr()和setattr()是一组内置函数,用于对对象的属性进行操作和查询,这篇文章... 目录1.getattr用法详解1.1 基本作用1.2 示例1.3 原理2.hasattr用法详解2.

MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)

《MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)》本文给大家介绍MyBatis的xml中字符串类型判空与非字符串类型判空处理方式,本文给大家介绍的非常详细,对大家的学习或... 目录完整 Hutool 写法版本对比优化为什么status变成Long?为什么 price 没事?怎

C#之枚举类型与随机数详解

《C#之枚举类型与随机数详解》文章讲解了枚举类型的定义与使用方法,包括在main外部声明枚举,用于表示游戏状态和周几状态,枚举值默认从0开始递增,也可手动设置初始值以生成随机数... 目录枚举类型1.定义枚举类型(main外)2.使用生成随机数总结枚举类型1.定义枚举类型(main外)enum 类型名字

Python lambda函数(匿名函数)、参数类型与递归全解析

《Pythonlambda函数(匿名函数)、参数类型与递归全解析》本文详解Python中lambda匿名函数、灵活参数类型和递归函数三大进阶特性,分别介绍其定义、应用场景及注意事项,助力编写简洁高效... 目录一、lambda 匿名函数:简洁的单行函数1. lambda 的定义与基本用法2. lambda

C语言自定义类型之联合和枚举解读

《C语言自定义类型之联合和枚举解读》联合体共享内存,大小由最大成员决定,遵循对齐规则;枚举类型列举可能值,提升可读性和类型安全性,两者在C语言中用于优化内存和程序效率... 目录一、联合体1.1 联合体类型的声明1.2 联合体的特点1.2.1 特点11.2.2 特点21.2.3 特点31.3 联合体的大小1

MySQL 索引简介及常见的索引类型有哪些

《MySQL索引简介及常见的索引类型有哪些》MySQL索引是加速数据检索的特殊结构,用于存储列值与位置信息,常见的索引类型包括:主键索引、唯一索引、普通索引、复合索引、全文索引和空间索引等,本文介绍... 目录什么是 mysql 的索引?常见的索引类型有哪些?总结性回答详细解释1. MySQL 索引的概念2