先定义了一个“有理数”(rational)类:

package ch6_classes_and_objects/*** 以Class的形式定义一个有理数的类型*/
class Rational(n : Int , d : Int) {/*** 求公约数*/private def gcd( x : Int , y : Int) : Int = {if ( x == 0 ) y else if ( x < 0 ) gcd ( -x , y )else if ( y < 0 ) -gcd ( x , -y)else gcd ( y % x , x)    }private val g = gcd ( n , d) // 分子,分母的最大公约数
  val number : Int = n / g val denom : Int = d / gdef +(that : Rational) = new Rational(number * that.denom + that.number * denom , denom * that.denom)def -(that : Rational) = new Rational(number * that.denom - that.number * denom , denom * that.denom)}

私有成员:这个类里定义一个私有方法:gcd,用来计算最大公约数。还有一个私有成员g ,用来持有构造参数(n , d)的最大公约数。这些变量在Rational类外部是不能访问到的。这些是用来保证分子(numerator)和分母(denominator)在一个正常的格式里。

创建和访问对象:以下的例子用来展示如何使用这个类的:

var i = 1
var x = new Rational(0 , 1)
while(i < = 10){x += new Rational(1 , i )i += 1
}
println("" + x.number + "/" + x.denom)

继承(Inheritance)和重写(Overriding):Scala里每个类都有一个超类(superClass)。如果没有明写出来,默认就是继承自scala.AnyRef类。一个类会继承父类所有的成员,当然,它也可以再重写(override)它们。比如toString方法。不过要注意的是,跟Java不同的是,Scala里,重定义的要在变量要在前面加上一个override标识符。

  与Java里的继承一样,如果A类继承自B类,那么A可以用在所在需要B类型的地方。说类型A遵从(conform to)类型B。也即如下正确:

var x : AnyRef = new Rational(1 , 2)

省略参数的方法(Parameterless Methods):不像Java,Scala里的方法不一定要带参数列表。如下面的square方法:

def square = new Rational(number * number , denom * denom)val r = new Rational(3 , 4)
println(r.square)

也就是说,无参的方法可以像值参数一样的访问。值和无参方法间的不同就是在于它们的定义。val的右侧值在对象被创建时就被计算出来,并且不再变换。而无参方法右侧的值只是在每次被调用的时候再进行计算。这种对属性和无参方法进行统一访问的方式使类实现变得可扩展。通常,一个版本中的一个属性会在下个版本中变成计算得到的值。统一访问保证了客户端不会因这种变化而重写。

抽象类

abstract class IntSet{def incl(x : Int) : IntSetdef contains(x : Int) : Boolean
}

IntSet这个类被标记为abstract class . 它有两个结果。首先,抽象类可能有声明的(declared)但没有实现的委托(deferred)成员。在上面这个例子里,incl和contains就是这样的成员。其次,因为一个抽象类可能有未实现的成员,所以不能用new 来创建一个这个类的对象。相反地,抽象类可以用来作为其他类的基本类(base class ),这些子类要实现这个委托成员(deferred members)。

特质(trait):abstract class 类似的,在Scala里也可以用关键字trait 来表示。特质是用来被加到其他类里的抽象类。另一个应用场景,就像Java里的接口(interface)一样,用来收集一些不同类中的通用功能。也可以如下定义上面的IntSet类

trait IntSet{def incl(x : Int) : IntSetdef contains(x : Int) : Boolean
}

实现抽象类:现在我们打算用二叉树来实现集合。有两种可能性,一种树是空集合(empty set),另一种是由一个整数和两个子树组成。以下是实现的代码:

EmptySet:

class EmptySet extends IntSet {def incl(x: Int): IntSet = { null }def contains(x: Int): Boolean = false }

NonEmptySet:

class NonEmptySet( elem : Int , left : IntSet , right : IntSet) extends IntSet {def incl(x: Int): IntSet = if ( x < elem) new NonEmptySet(elem , left incl(x) , right)else if ( x > elem ) new NonEmptySet(elem , left , right incl(x))else thisdef contains(x: Int): Boolean = if ( x < elem) left contains x else if ( x > elem ) right contains xelse true }

两个类都是继承自IntSet,所以都可以用在所在需要IntSet类型的地方。

动态绑定(dynamic binding):面向对象的语言都是用动态发送(dynamic dispatch)的方式给方法的调用。即调用一个方法依赖于包含这个方法的对象的运行进类型(run-time type)。(可以理解成类似于多态的意思?)Scala把所有的函数都当成对象来对待。

对象(objects):在之前的代码里,用表达式:new EmptySet 来创建了一个EmptySet的对象,所以,可以在任何需要空集合的时候通过这种方式来创建一个空集合。例如:

val EmptySetVal = new EmptySet

来创建一个新的空集合。但有一个问题:这么定义的值不是一个合法的Scala顶级(top-level)定义。因为它必须成为另一个类或对象的某个部分。一个更为直接点的方法,就是用object 来作定义。以下是一个合理化的可选的定义一个空集合对象:

object EmptySet extends IntSet{def contains(x : Int) : Boolean = falsedef incl(x : Int) : IntSet = new NonEmptySet(x , EmptySet , EmptySet)
}

因为它可以不用像类一样的使用new 来创建,而是可以直接使用(注:有点类似于Java中的静态类),那这个对象是何时创建的?回答是它其中的一个成员第一次被访问的时候,这个对象就创建出来了。这个策略叫作延迟赋值(lazy evaluation。是不是也可以叫“懒加载”)。

标准类:Scala是一个纯粹的面向对象的语言。意味着Scala里的所有值都可以当成对象。甚至连基本类型int , boolean都没有特殊对待。它们被当成Scala类的简写,被定义在Predef中:

type boolean = scala.Boolean
type int = scala.Int
type long = scala.Long

(之后给出了标准库中Boolean 对象的定义。略过)。还举例了一个“自然数”的定义。之后再看。

转载于:https://www.cnblogs.com/peterzd/archive/2012/04/11/2440149.html

《Scala By Examples》第6章 类和对象相关推荐

  1. Kotlin学习笔记 第二章 类与对象 第十二 十三节 对象表达式与对象声明 类型别名

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  2. Kotlin学习笔记 第二章 类与对象 第三节接口 第四节 函数式接口

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  3. 第三章类与对象基础 ① 笔记

    1. 内容回顾 1.1. 课前测试 1.2. 上节内容 2. 本章重点 2.1. 类和对象的概念 2.2. 类的基本组成 2.3. 构造方法 2.4. 成员方法 3. 具体内容 3.1. 类和对象的概 ...

  4. java怎么给类中的私有变量赋值_Java核心技术笔记分享------第二章 类与对象

    对象与类 一.面向对象思想的概述 1>面向对象与面向过程: 二者都是一种思想,面向对象是相对于面向过程而言的.面向过程强调的是功能行为.面向对象,将功能封装进对象,强调具备了功能的对象. 面向对 ...

  5. Python程序开发——第六章 类与对象

    目录 一.类 (一)类.对象 (二)类的定义 (三)对象的创建和使用 二.限制对象访问 (一)定义私有成员.方法 (二)访问私有成员.方法 三.构造方法和析构方法 (一)构造方法 (二)析构方法 四. ...

  6. 第四章类和对象 习题答案

    一.选择题1.能提供封装的C++的下列关键字是(C)A.whileB. unionC. classD. for2.在下面所列项中,不是面向对象的特点的是(C)A. 多面性B. 抽象性和封装性C. 多线 ...

  7. JAVA入门第二季 第一章 类和对象

    面向对象编程 Object Oriented Programming OOP 第一.什么是类和对象 在具体说明类和对象之前,先说说别的. 眼睛在人类身体上最为有用的器官.如果一个没有了眼睛,这个人与世 ...

  8. C++语言程序设计——知识点复盘(第四章 类与对象)

    目录 面向对象程序设计的基本特点 1.抽象 2.封装 3.继承 4.多态 类和对象 类的成员函数 1.成员函数的实现 2.目的对象. 3.带默认形参值的成员函数 4.内联成员函数 构造函数 析构函数 ...

  9. 第四章——类和对象(一)

    c++面向对象的三大特性:封装.继承.多态 4.1封装 4.1.1封装的意义 封装的意义 将属性和行为作为一个整体,表现生活中的事物 将属性和行为加以权限控制 封装意义一: 在设计类的时候,属性和行为 ...

最新文章

  1. Linux基础知识题解答(一)
  2. nginx 官方手册 php,nginx + php 的配置
  3. caffe训练输入数据格式介绍(LMDB/imagelist)
  4. QT每日一练day28:QT中的2D绘图知识概念——讲义截图
  5. 检验密码强度的JS类(from thin's blog)
  6. 票据的生命周期与人的灵魂
  7. 【实战】NLP命名实体识别开源实战教程
  8. Python学习之面向对象(一)
  9. iPad mini2 Vieux降级ios10.3.3 问题解决合集
  10. 远程计算机桌面图标不见了怎么办,远程桌面图标不见了怎么办
  11. gorm中使用where in 条件
  12. 小的以及大的Typhon IDE
  13. 安全日志分析的五种类型
  14. python4delphi和tesserocr库安装配置
  15. 优秀广告设计作品常用的几大设计思维
  16. guido正式对外发布python版本的年份_Guido van Rossum正式对外发布Python版本的年份是:______。...
  17. 通过Docker容器搭建私有网盘(NextCloud)
  18. 蓝牙路由器蓝牙点对多点组网蓝牙远程控制
  19. 王者荣耀刷金币脚本,买英雄你还愁么?
  20. Concept Whitening for interpretable image recognition 用于可解释图像识别的概念白化

热门文章

  1. LeetCode Construct Binary Tree from Inorder and Postorder Traversal
  2. Spring boot 梳理 - 在bean中使用命令行参数-自动装配ApplicationArguments
  3. [luogu2576 SCOI2010] 幸运数字 (容斥原理)
  4. Partition List
  5. bzoj1013球形空间
  6. ajax实现文件上传,多文件上传,追加参数
  7. 前序,中序,后序遍历
  8. E: Could not get lock /var/lib/dpkg/lock解决
  9. CAShapeLayer和CAGradientLayer
  10. C# 获取字符串长度 获取字符串字节长度