作者:摇摆少年梦

视频地址:http://www.xuetuwuyou.com/course/12

本节主要内容

  1. this.type使用
  2. 类型投影
  3. 结构类型
  4. 复合类型

1. this.type使用


class Person{
private var name:String=null
private var age:Int=0
def setName(name:String)={
this.name=name
//返回对象本身
this
}
def setAge(age:Int)={
this.age=age
//返回对象本身
this
}
override def toString()="name:"+name+" age:"+age
} object Main extends App{
//链式调用
println(new Person().setAge(18).setName("摇摆少年梦"))
}

当涉及到继承时,这样的机制会存在些问题,比如:

class Person{
private var name:String=null
private var age:Int=0
def setName(name:String)={
this.name=name
//返回Person对象本身
this
}
def setAge(age:Int)={
this.age=age
//返回Person对象本身
this
}
override def toString()="name:"+name+" age:"+age
} class Student extends Person{
private var studentNo:String=null
def setStudentNo(no:String)={
this.studentNo=no
this
}
override def toString()=super.toString()+" studetNo:"+studentNo
} object Main extends App{
//以下的代码会报错
//value setStudentNo is not a member of cn.scala.xtwy.advancedtype.Person
println(new Student().setName("john").setAge(22).setStudentNo("2014"))
}

Student对象在调用setName、setAge方法时,返回的对象类型实质上仍然是Person类型。而Person类型并没有setStudentNo方法,从而编译出错。为解决该问题,能够将setName、setAge方法的返回值设置为:this.type ,代码例如以下:

class Person{
private var name:String=null
private var age:Int=0
//this.type返回实际类型
def setName(name:String):this.type={
this.name=name
this
}
def setAge(age:Int):this.type={
this.age=age
this
}
override def toString()="name:"+name+" age:"+age
} class Student extends Person{
private var studentNo:String=null
def setStudentNo(no:String)={
this.studentNo=no
this
}
override def toString()=super.toString()+" studetNo:"+studentNo
} object Main extends App{
//println(new Person().setAge(18).setName("摇摆少年梦"))
println(new Student().setName("john").setAge(22).setStudentNo("2014"))
}

2. 类型投影

我们知道,Scala中的内部类同类成员一类,仅仅只是它被定义一个类而已。它具有例如以下的訪问创建方式:

class Outter{
private var x:Int=0
//内部类Inner
class Inner{
def test()=x
}
} object TypeProject extends App{
val outter=new Outter
//创建内部类的方式。同訪问正常的成员变量一样
val inner=new outter.Inner
println(inner.test()) }

那Scala语言中不同对象创建的内部类是不是同一个类呢?事实上不是,以下的代码就是证明:


import scala.reflect.runtime.universe.typeOf
class Outter{
private var x:Int=0
def print(i:Inner)=i
class Inner{
def test()=x
}
} object TypeProject extends App{
val outter=new Outter
val inner=new outter.Inner val outter2=new Outter
val inner2=new outter2.Inner //以下的代码编译会失败
//outter.print(inner2)
//这是由于不同outter对象相应的内部类成员类型是不一样的
//这就跟两个类成员的实例它们内存地址不一样相似 //以下的类型推断会输出false
//这也进一步说明了它们类型是不一样的
println(typeOf[outter.Inner]==typeOf[outter2.Inner]) }

上述代码中Outter类中的def print(i:Inner)=i 成员方法中的參数类型Inner事实上相当于def print(i:this.Inner)=idef print(i:Outter.this.Inner)=i ,也即它依赖于外部类。总体的话构成了一路径。由于也称为路径依赖类型。

再看下内部类的几种使用情况。它相应几种不同的路径依赖类型:

(1)类内部本身使用情况

class Outter{
private var x:Int=0
//内部使用,相当于
//private var i:Inner=new Outter.this.Inner
private var i:Inner=new Inner
def print(i:Inner)=i
class Inner{
def test()=x
}
}

(2)子类使用父类中的内部类

class Outter{
private var x:Int=0
def print(i:Inner)=i
class Inner{
def test()=x
}
}
//子类中使用父类中的内部类
class A extends Outter{
private val i=new A.super.Inner
}

(3)在其他类或对象中使用

object TypeProject extends App{
val outter=new Outter
val inner=new outter.Inner val outter2=new Outter
val inner2=new outter2.Inner
}

明确几种路径依赖类型之后,我们能够对类型投影进行说明:类型投影的目的是将外部类Outter中定义的方法def print(i:Inner)=i。它能够接受做随意外部类对象中的Inner类。

上面的样例当中outter与outter2中的Inner类型具有共同的父类。

例如以下图所看到的:

代码例如以下:

import scala.reflect.runtime.universe.typeOf
class Outter{
private var x:Int=0
private var i:Inner=new Outter.this.Inner
//Outter#Inner类型投影的写法
//能够接受不论什么outter对象中的Inner类型对象
def print(i:Outter#Inner)=i
class Inner{
def test()=x
}
} class A extends Outter{
private val i=new A.super.Inner
} object TypeProject extends App{
val outter=new Outter
val inner=new outter.Inner val outter2=new Outter
val inner2=new outter2.Inner
//以下的这个语句能够成功运行
outter.print(inner2)
//注意,以下的这条语句返回的仍然是false。我们仅仅是对print方法中的
//參数进行类型投影,并没有改变outter.Inner与outter2.Inner
//是不同类的事实
println(typeOf[outter.Inner]==typeOf[outter2.Inner])
}

3. 结构类型

结构类型(Struture Type)通过利用反射机制为静态语言加入动态特性。从面使得參数类型不受限于某个已命名的的类型,比如:

object StructureType {
//releaseMemory中的方法是一个结构体类型,它定义了
//一个抽象方法,对close方法的规格进行了说明
def releaseMemory(res:{def close():Unit}){
res.close()
} def main(args: Array[String]): Unit = {
//结构体使用方式
releaseMemory(new {def close()=println("closed")})
}
}

另外结构体类型还能够用type关键字进行声明,如:

object StructureType {
def releaseMemory(res:{def close():Unit}){
res.close()
}
//採用关键字进行结构体类型声明
type X={def close():Unit}
//结构体类型X作为类型參数。定义函数releaseMemory2
def releaseMemory2(x:X)=x.close() def main(args: Array[String]): Unit = {
releaseMemory(new {def close()=println("closed")})
//函数使用同releaseMemory
releaseMemory2(new {def close()=println("closed")})
}
}

从上面的代码来看,结构体类型事实上能够看作是一个类,在函数调用时,直接通过new操作来创建一个结构体类型对象,当然它是匿名的。因此,上述方法也能够传入一个实现了close方法的类或单例对象

//定义一个普通的scala类,当中包括了close成员方法
class File{
def close():Unit=println("File Closed")
}
//定义一个单例对象,当中也包括了close成员方法
object File{
def close():Unit=println("object File closed")
} object StructureType {
def releaseMemory(res:{def close():Unit}){
res.close()
}
type X={def close():Unit}
def releaseMemory2(x:X)=x.close() def main(args: Array[String]): Unit = {
releaseMemory(new {def close()=println("closed")})
releaseMemory2(new {def close()=println("closed")}) //对于普通的scala类,直接创建对象传入就可以使用前述的方法
releaseMemory(new File())
//对于单例对象,直接传入单例对象就可以
releaseMemory(File)
}
}

我们能够看到,尽管说定义的方法中的參数是一个结构体类型,可是我们也能够传入普通类对象和单例对象,仅仅要该对象或类中具有结构体类型中声明的方法就可以。上述代码也告诉 我们。事实上结构体类型也是一个类。仅仅是表现形式与类有所差别而已。

4. 复合类型

复合类型在前面的课程中事实上我们已经有过接触。比如

class B extends A with Cloneable

总体 A with Cloneable能够看作是一个复合类型。它也能够通过type关键字来进行声明,比如:


class B extends A with Cloneable object CompoundType {
//利用关键字type声明一个复合类型
type X=A with Cloneable
def test(x:X)=println("test ok")
def main(args: Array[String]): Unit = {
test(new B)
}
}

加入公众微信号。能够了解很多其他最新Spark、Scala相关技术资讯

Scala入门到精通——第二十二节 高级类型 (一)的更多相关文章

  1. Scala入门到精通——第二十四节 高级类型 (三)

    作者:摆摆少年梦 视频地址:http://blog.csdn.net/wsscy2004/article/details/38440247 本节主要内容 Type Specialization Man ...

  2. Scala入门到精通——第二十九节 Scala数据库编程

    本节主要内容 Scala Mavenproject的创建 Scala JDBC方式訪问MySQL Slick简单介绍 Slick数据库编程实战 SQL与Slick相互转换 本课程在多数内容是在官方教程 ...

  3. Scala入门到精通——第二十七节 Scala操纵XML

    本节主要内容 XML 字面量 XML内容提取 XML对象序列化及反序列化 XML文件读取与保存 XML模式匹配 1. XML 字面量 XML是一种很重要的半结构化数据表示方式,眼下大量的应用依赖于XM ...

  4. Scala入门到精通

    原文出自于: http://my.csdn.net/lovehuangjiaju 感谢! 也感谢,http://m.blog.csdn.net/article/details?id=52233484 ...

  5. SaltStack 入门到精通第二篇:Salt-master配置文件详解

    SaltStack 入门到精通第二篇:Salt-master配置文件详解     转自(coocla):http://blog.coocla.org/301.html 原本想要重新翻译salt-mas ...

  6. 网络安全从入门到精通(第二章-3)后端基础SQL— MySQL高级查询与子查询

    本文内容: MySQL的基础查询语句 链接查询 联合查询 子查询 渗透测试常用函数 1,MySQL基础查询语句: select * from 表 order  by ASC/DESC; ASC:从小到 ...

  7. Scala入门到精通——第十五节 Case Class与模式匹配(二)

    本节主要内容 模式匹配的类型 for控制结构中的模式匹配 option类型模式匹配 1. 模式的类型 1 常量模式 object ConstantPattern{ def main(args: Arr ...

  8. Scala入门到精通——第十九节 隐式转换与隐式參数(二)

    作者:摇摆少年梦 配套视频地址:http://www.xuetuwuyou.com/course/12 本节主要内容 隐式參数中的隐式转换 函数中隐式參数使用概要 隐式转换问题梳理 1. 隐式參数中的 ...

  9. Scala入门到精通——第十六节 泛型与注解

    本节主要内容 泛型(Generic Type)简单介绍 注解(Annotation)简单介绍 注解经常使用场景 1. 泛型(Generic Type)简单介绍 泛型用于指定方法或类能够接受随意类型參数 ...

随机推荐

  1. 26. Intellij IDEA 启动项目ClassNotFoundException

    转自:https://blog.csdn.net/zhw0596/article/details/81388147 使用Intellij IDEA  的过程中,新创建的项目启动时报 严重: Error ...

  2. js数组去重的常用方法总结

    最近几天朋友面试了几家,笔试题都做了关于数组去重的问题,自己在网上收集整理了一些去重的方法来学习下,感觉换不错哈!!!第一种方法: function oSort(arr){ var n = []; / ...

  3. 初学PHP&MySQL 2014-05-31 12:40 92人阅读 评论(0) 收藏

    PHP echo  print 都能输出文本 date(format,timestamp)可以格式化时间戳 mktime()可以返回指定日期的时间戳 include 'filename'或者 requ ...

  4. 是时候抛弃web.xml了?

    你是否再为配置文件web.xml容易出错而烦恼?是否为web.xml文件存放位置而不知所措?是否为web.xml为什么要这样配?怎么才能更好的配置web.xml而烦恼?那么一种新的方式出现了: spr ...

  5. 关于jacob支持BSTR类型的经验总结

    作者:朱金灿 来源:http://blog.csdn.net/clever101 jacob是实现Java和COM之间互操作的一个开源中间件.网上大多的程序示例基本上是使用jacob调用微软的offi ...

  6. Reference Counting GC (Part two :Partial Mark & Sweep)

    目录 部分标记清除算法 前提 dec_ref_cnt()函数 new_obj()函数 scan_hatch_queue()函数 paint_gray()函数 scan_gray()函数 collect ...

  7. 【Henu ACM Round #13 D】A Trivial Problem

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 123...n中末尾0的个数 只会由素因子2和5的个数决定且等于 Min{cnt[2],cnt[5]} 且素因子2的个数一定会比5多 ...

  8. 【Uva 1627】Team them up!

    [Link]: [Description] 给你n个人; 有一些人之间有认识关系 a认识b,b不一定认识a 让你把这n个人分成两组 使得这两组中的每一组: 组内的人与人之间都相互认识. 并且,使得两组 ...

  9. QCAD Plugin 开发

    QCAD Plugin 开发 eryar@163.com Abstract. QCAD是基于GPL协议的开源CAD软件,核心功能基于Qt使用C++开发,界面及其交互使用Javascript脚本进行开发 ...

  10. SQL 增删改查(具体)

    一.增:有3种方法 1.使用insert插入单行数据: insert [into] <表名> [列名] values <列值> insert into Strdents (na ...