Scala学习笔记(3): 面向对象与容器

转载 2016年05月31日 10:44:41

面向对象编程

这个通过一个例子来解释Scala面向对象编程的基本概念,这里我们需要为MongoDB(一种NoSQL数据库,详见我的另一篇博客)编写一个简单的API。MongoDB官方提供了Java API,而我们要做的是使用Scala对其进行简单的封装。

Class

先来搭建一个叫MongoClient的类作为建立数据库连接的入口,定义一个MongoClient类,并指定主构造函数的两个参数(val host: String, val port: Int)。

class MongoClient(val host: String, val port: Int)

构造函数参数的格式可以是[val/var] param : type,区别在于:val参数是只读的(相当于只有get方法),var参数是可写的(有get和set方法),如果没有前缀则是私有的(没有get和set方法)

构造函数

可以在类中定义多个构造函数(包括默认构造函数),例如下面是MongoClient的一个完整定义:

class MongoClient(val host: String, val port: Int) {
  
  require(host != null, "You have to provide a host name")
  private val underlying = new Mongo(host, port)

  def this() = this("127.0.0.1", 27017)
  def version = underlying.getVersion()
  def dropDB(name: String) = underlying.dropDatabase(name)
  def createDB(name: String) = DB(underlying.getDB(name))
  def db(name: String) = DB(underlying.getDB(name))
}

def this() 定义了一个默认构造函数。

Case class

case class是一种特殊的Class,编译器会为其自动生成一些样板代码(equals, hashCode, toString, apply等)。

case class Person(firstName:String, lastName:String)

Object

Scala中不存在静态变量和静态方法,所有的变量和方法必须定义在类或者定义在object中,所谓的object就是一个单例对象。

object可以用来定义一个可执行类:

object HelloWrold extends App {
    println("Hello World")
}

object可以定义

object的另一种常见的用法是作为一个类的伴随对象,用来定义一些“静态”的工厂函数。例如下面这段程序中,我们首先定义了DB类,然后定义了一个同样叫DB的伴随对象,伴随对象可以可以访问伴随类的私有成员。

class DB private (val underlying: MongoDB){ //注意private关键词,DB的构造函数是私有的
  def collectionNames = for(name <- new JSetWrapper(underlying.getCollectionNames())) yield name
  
  private def collection(name: String) = underlying.getCollection(name)
  
  def readOnlyCollection(name: String) = new DBCollection(collection(name))
  def administrableCollection(name: String) = new DBCollection(collection(name)) with Administrable
  def updatableCollection(name: String) = new DBCollection(collection(name)) with Updatable 
}

object DB {
  def apply(underlying: MongoDB) = new DB(underlying)
}

包与引入

Scala中包也是一种特殊的对象,在包内部可以看定义其他类与对象,如果要在包里面定义函数或者变量的话,请使用包对象:

//package.scala
package object bar {
  val minimumAge = 18
  def verifyAge = {}
}

//other.scala
package bar
class BarTender {
  def serveDrinks = { verifyAge; ... }
}

包的定义可以是嵌套式的(C#中常见),或者是平板式的(Java中常见)。引用包的常见写法有:

import com.mongodb.DBObject
import com.mongodb._  //_与Java中的×(星号)是一个意思
import com.mongodb.{DBCollection => MongoDBCollection} //引入包后更改其名称

Scala的继承模型

scala.Any是任何类的父类;Scala.AnyRef相当于Java中的Object类,即任何引用类的父类;AnyVal是任何值类的父类。

在图中实线表示继承关系,虚线表示view关系,view的意思是类型间存在隐式转换。

scala class.png

在类层级的最底下是Scala.Null和Scala.Nothing,Scala.Null类型只有一个实例化对象null, Scala.Nothing则不能实例化。

特质

Trait可以翻译成特质,你可以认为特质是一种增强版的接口,但我认为把它理解为一种部分实现的类更为合适。为什么这么说?因为使用特质构造程序,允许我们把一个大的类打散成多个特质,相当于把机器拆成零件,然后再自由组装。

特性 Interface (Java) Abstract class (Java + Scala) Trait
实例化 No No No
构造参数 No Yes No
方法定义 Yes Yes Yes
方法实现 No Yes Yes
成员变量 No Yes Yes
多重组合(继承) Yes No Yes

例如下面这个例子中,我们把mongodb java API的功能打散成几个不同的特质,所以特质都从ReadOnly特质继承而来。

trait ReadOnly {
  val underlying : MongoDBCollection
  
  def name = underlying getName
  def fullName = underlying getFullName
  def find(doc: DBObject) = underlying find doc
  def findOne(doc: DBObject) = underlying findOne doc
  def findONe = underlying findOne
  def getCount(doc: DBObject) = underlying getCount doc
  
  def find(query: Query): DBCursor = {
    def applyOptions(cursor:DBCursor, option: QueryOption): DBCursor = {
    option match {
      case Skip(skip, next) => applyOptions(cursor.skip(skip), next)
      case Sort(sorting, next)=> applyOptions(cursor.sort(sorting), next)
      case Limit(limit, next) => applyOptions(cursor.limit(limit), next)
      case NoOption => cursor
    }
    }
    applyOptions(find(query.q), query.option)
  }
}

trait Administrable extends ReadOnly {
  
  def drop: Unit = underlying drop
  def dropIndexes : Unit = underlying dropIndexes
  
}

trait Updatable extends ReadOnly {
  def -=(doc: DBObject): Unit = underlying remove doc
  def +=(doc: DBObject): Unit = underlying save doc
}

trait LocaleAware extends ReadOnly {
  override def findOne(doc: DBObject) = {
    doc.put("locale", java.util.Locale.getDefault.getLanguage)
    super.findOne(doc)
  }
  override def find(doc: DBObject) = {
    doc.put("locale", java.util.Locale.getDefault.getLanguage)
    super.find(doc)
  }
}

class DBCollection(override val underlying: MongoDBCollection) extends ReadOnly

//用法
new DBCollection(mongoDBCollection) with Updatable with Administrable

Scala容器

Scala中容器被划分为两类:immutable和mutable,分别属于包 scala.collection.immutable和 scala.collection.mutable。Java程序员可以用String和StringBuffer的来理解它们的区别,即immutable容器上的增删操作会返回一个新的immutable容器,而mutable容器上的增删操作是in place(会产生副作用)。

所有immutable和mutable容器都继承自scala.collection里定义的抽象类,它的类结构如下:

scala-collection.png

  • IndexedSeq的实现是Vector, LinearSeq的实现是list
  • 通过使用隐式转换,Java中的String和Array类型在Scala中“继承”了IndexedSeq接口

常见的collection操作

  • map 使用函数f(T=>T)将collection中的元素映射到一个新的collection
  • flatMap 函数映射f(T=>List[T]),但会把collection扁平化
  • filter
  • foldLeft
  • foldRight

并发容器

Scala 2.9引入了并发容器,使得很多容器操作可以安全的并发执行。例如,在普通容器类后加.par后缀即可转换为并发容器。

myCollection.par.foldLeft(0)((a,b) => a+b)

Par容器的内部实现是基于类似于MergeSort的分割组合算法。


Scala学习之路----面向对象编程

Scala是一门多范式的编程语言,一种类似java的编程语言,设计初衷是实现可伸缩的语言、并集成面向对象编程和函数式编程的各种特性。...
  • lovelzllove
  • lovelzllove
  • 2017年03月19日 15:01
  • 268

scala学习三:scala面向对象

scala学习三:scala面向对象标签(空格分隔): scalascala学习三scala面向对象 一面向对象的基本概念 二构造器 三object 四scala中的apply方法 五继承 一,面向对...
  • youfashion
  • youfashion
  • 2016年06月12日 19:49
  • 1182

【C++面向对象学习笔记】-基础知识

1.基本概念 面向对象程序设计是利用对象来进行程序设计。一个对象表示现实世界中一个独一无二的实体。例如,一名学生、一张桌子、一个圆等都可以看作对象。一个对象具有唯一的身份、状态和行为。一个对象的状态...
  • Kevin_zhai
  • Kevin_zhai
  • 2015年09月08日 16:58
  • 3509

Scala语言:集成面向对象和函数式编程的特性

简介 Scala编程语言近来抓住了很多开发者的眼球。如果你粗略浏览Scala的网站,你会觉得Scala是一种纯粹的面向对象编程语言,而又无缝地结合了命令式和函数式的编程风格。Christopher ...
  • jmppok
  • jmppok
  • 2013年12月11日 15:51
  • 2304

BC404学习笔记-ABAP面向对象编程(一)-基础

只摘录注意事项和难以理解的地方。总的来说和JAVA、C++面向对象编程技术差不太多。类、继承、封装之类的概念在abapoo中也都有体现。面向对象的对象简单理解就是现实世界的事物,到编程世界就用类来表现...
  • yang362046076
  • yang362046076
  • 2016年04月12日 10:16
  • 1062

Scala学习笔记之面向对象

Scala 目录(?)[-] 创建对象object单例对象object和类的区别伴生对象互相引用scala继承结构包前缀方法对象相等导入导入类构造器thisjava和scala中的构造顺序...
  • ichsonx
  • ichsonx
  • 2014年11月10日 14:05
  • 1147

Java复习笔记—面向对象

面向对象 特点:1:将复杂的事情简单化。 2:面向对象将程序员从执行者,变成了指挥者。 3:面向对象这种思想是符合现在人们思考习惯的一种思想。   面向对象的过程:其实就是不断创造对象,适用...
  • gk1023
  • gk1023
  • 2015年10月05日 20:35
  • 360

Scala面向对象彻底精通及Spark源码阅读

1.Scala中的类、object实战讲解 java8前 :类或对象中新增加一个方法,方法中本身调用其他方法,写匿名内部类写个方法,回调, java8 lamada解决了此问题 scala (无...
  • sundujing
  • sundujing
  • 2016年05月03日 18:18
  • 1432

学习java中面向对象的一些小总结。

Java面向对象 面向对象三大特征:封装、继承、多态   封装:1.提高数据的安全性。 2.操作简单 3.隐藏了实现 使用private修饰需要封装的属性,用set和get设置和获取属性。   构造函...
  • xs_challenge
  • xs_challenge
  • 2016年11月17日 20:13
  • 832

以一个简单的项目来学习面向对象编程(设计模式和多线程)

下面的项目是两年前学校老师布置的一个小项目,当时自己用了一种很笨拙的方式实现了,现在用面向对象的思想和多线程重构这个项目。问题描述:西宝高速仿真模拟 西安市到宝鸡市之间是我省主要的高速公路客运路线之...
  • yang_yulei
  • yang_yulei
  • 2015年03月09日 20:44
  • 2843
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Scala学习笔记(3): 面向对象与容器
举报原因:
原因补充:

(最多只允许输入30个字)