函数化对象(又称方程化对象)指的是所定义的类或对象不包含任何可以修改的状态。

本篇随笔就是着重记录函数化对象。定义了一个有理数类定义的几个不同版本,以介绍 Scala 类定义的几个特性:类参数和构造函数,方法,操作符,私有成员,重载,过载,条件检查,引用自身。

一、Rational类的定义

  Rational类定义一个有理数。一个有理数可以表示为n/d,其中n、d都是整数(d != 0)。与浮点数相比,有理数可以精确的表示一个分数,而不会有误差。

二、定义Rational

  Rational类暂定义如下:

class Rational(n:Int, d:Int){
println("Rational " + n + "/" + d)
}

  从上面的定义可以看出,与 Java 不同的是,Scala 的类定义可以有参数,称为类参数。

Scala处理使用类参数外,还把类定义和主构造函数合并在一起,在定义类的同时也定义了类的主构造函数。

Scala类的主构造函数是指类中任何不属于类成员和类方法的其他代码,Scala编译器会编译这个代码。

三、重新定义类的toString方法

重新定义类的方法时需要使用关键字——override——修饰。

重新定义方法toString的代码如下:

class  Rational(n:Int, d:Int){
override def toString = n + "/" + d
}

  如果不重新定义toString方法,就是缺省实现println(new Rational(3, 2) 打印出来对象的类名称+@+16进制数。

四、前提条件检查

当类的创建有先决条件时,例如有理数的分母不能为0,Scala中可以使用require方法。加入前提条件检查后的代码如下:

class  Rational(n:Int, d:Int){
require(d != 0)
override def toString = n + "/" + d
}

五、添加成员变量

尽管类参数在新定义的函数的访问范围之内,但仅限于定义类的方法本身(比如之前定义的 toString 方法,可以直接访问类参数),但对于 that 来说,无法使用 that.d 来访问 d 。

这时候可以使用类的成员变量,添加成员变量之后的代码如下:

class  Rational(n:Int, d:Int){
require(d != 0) val number = n
val denom = d override def toString = n + "/" + d def add(that:Rational) = new Rational
(number * that.denom + that.number * denom, denom * that.denom)
}

上述代码中添加了一个方法 add,实现两个Rational对象相加。

六、自身引用

可以使用this来引用当前对象的本身,这点与Java相同。一般来说访问类成员时无需使用this;如果需要引用对象本身则this不能shenglve。

第一种:

def lessThan(that:Rational) =
this.number * that.denom < that.number * this.denom

第二种:

def lessThan(that:Rational) =
number * that.denom < that.number * denom
def max(that:Rational) =
if(lessThan(that)) that else this

  

七、辅助构造函数

又称从构造函数,指除主构造函数之外的构造函数。

所有 Scala 的辅助构造函数的第一个语句都为调用其它构造函数,也就是 this(…) 。被调用的构造函数可以是主构造函数或是其它构造函数(最终会调用主构造函数)。这样使得每个构造函数最终都会调用主构造函数,从而使得主构造函数称为创建类单一入口点。

在 Scala 中也只有主构造函数才能调用基类的构造函数,这种限制有它的优点,使得 Scala 构造函数更加简洁和提高一致性。

下面的代码定义了一个从构造函数,用来初始化分母为1的有理数,代码如下:

class  Rational(n:Int, d:Int){
require(d != 0) val number = n
val denom = d override def toString = n + "/" + d def this(n:Int) = this(n, 1) def add(that:Rational) = new Rational
(number * that.denom + that.number * denom, denom * that.denom)
}

八、私有成员变量和方法

Scala中定义私用成员变量和方法使用private修饰。下面的代码为增加了一个私有成员变量和一个私用方法,求最大公约数。代码如下:

class Rational (n:Int, d:Int) {
require(d!=0) private val g =gcd (n.abs,d.abs) val number =n/g
val denom =d/g
override def toString = number + "/" +denom
def add(that:Rational) =
new Rational( number * that.denom + that.number* denom, denom * that.denom) def this(n:Int) = this(n,1) private def gcd(a:Int,b:Int):Int =
if(b==0) a else gcd(b, a % b)
}

  

九、定义运算符

在Scala中运算符(操作符)和普通方法没有什么区别,任何方法都可以写成操作符的方法。 例如 new Rational(3,2) add new Rational(5,2)是可以正确执行的。除此之外,也可以将方法add写成方法+,代码如下:

class  Rational(n:Int, d:Int){
require(d != 0) val number = n
val denom = d override def toString = n + "/" + d def +(that:Rational) = new Rational
(number * that.denom + that.number * denom, denom * that.denom)
}

  

十、Scala中的标识符

Scala 可以使用两种形式的标志符,字符数字和符号。字符数字使用字母或是下划线开头,后面可以接字母或是数字,符号 $ 在 Scala 中也看作为字母。然而以 $ 开头的标识符为保留的Scala编译器产生的标志符使用,应用程序应该避免使用 $ 开始的标识符,以免造成冲突。(解析公式失败)

Scala 的命名规则采用和 Java 类似的 camel 命名规则(驼峰命名法),首字符小写,比如 toString 。类名的首字符还是使用大写。此外也应该避免使用以下划线结尾的标志符以避免冲突。

十一、方法重载

重载的方法参数类型不同而使用同样的方法名称。

def  +(i:Int) = new Rational(number + i * denom, denom)

  例如在Rational类中加入上面的代码,就是对方法+的重载。

十二、隐式类型转换

new Rational(3, 2) + 2 可以计算出正确的结果,但是 2 + new Rational(3, 2) 就会出错。这是因为 2 是整型,不能自动转换成Rational类型,Scala中提供的隐式类型转换可以实现这种操作。

定义一个隐式类型转换使用关键词 implicit  def.

Int型隐式转换成Rational类型的方法代码如下:

implicit  def  intToRational(x:Int) = new Rational(x)

Scala学习随笔——深入类和对象的更多相关文章

  1. Java学习笔记之---类和对象

    Java学习笔记之---类和对象 (一)类 类是一个模板,它描述一类对象的行为和状态  例如:动物类是一个类,动物们都有属性:颜色,动物们都有行为:吃饭 public class Dog { Stri ...

  2. Scala学习随笔——Scala起步

    实验楼学习Scala语言的笔记,课程网址为https://www.shiyanlou.com/courses/490 一.Scala简介 Scala 是一门多范式的编程语言,类似于 Java .设计初 ...

  3. 学习笔记——Java类和对象

    今天学习了Java的类和对象的相关知识,由于Java面向对象的编程的思想和C++几乎一样,所以需要更多的关注Java的一些不同之处. 1.类 1.1 在类这一块,除了基本的成员变量,成员方法,构造函数 ...

  4. spark快速开发之scala基础之3类,对象,特征

    类 scala的类定义非常灵活 class test4 class test2{} class test3(x:Int) 定义一个带构造函数的类 class Point (x : Int,y : In ...

  5. [Scala]Scala学习笔记四 类

    1. 简单类与无参方法 class Person { var age = 0 // 必须初始化字段 def getAge() = age // 方法默认为公有的 } 备注 在Scala中,类并不声明为 ...

  6. 【Python学习之七】类和对象

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 python3.6 一.面向对象编程1.概念(1)面向对象编程(OOP ...

  7. Java学习笔记 04 类和对象

    一.类和对象的概念 类 >>具有相同属性和行为的一类实体 对象 >>实物存在的实体.通常会将对象划分为两个部分,即静态部分和动态部分.静态部分指的是不能动的部分,被称为属性,任 ...

  8. Java学习第二篇:类,对象,成员属性,成员方法,构造方法,类变量,类方法

    一.类的定义 一个全面的类定义是比较复杂的,  定义如下:

  9. php学习小记2 类与对象

    php类的一些特性: 1. 伪变量$this.$this是一个到主叫对象的引用.取值:该方法所从属的对象,可能是另外的对象(前提,当该方法被静态调用时).$this变量存在于一个类的非静态方法中,在静 ...

随机推荐

  1. 小白日记54:kali渗透测试之Web渗透-补充概念(AJAX,WEB Service)

    补充概念 AJAX(异步javascript和XML) Asynchronous javascript and xml 是一个概念,而非一种新的编程语言,是一组现有技术的组合 通过客户端脚本动态更新页 ...

  2. TopCoder SRM 710 Div2 Hard MinMaxMax Floyd最短路变形

    题意: 有一个无向连通图,没有重边没有自环,并给出顶点的权值和边的权值 定义一条路径\(difficulty\)值为该路径上最大的点权乘上最大的边权 定义函数\(d(i,j)\)为\(i,j\)之间的 ...

  3. Java重写与重载

    重写的规则: 参数列表必须完全与被重写方法的相同: 返回类型必须完全与被重写方法的返回类型相同: 访问权限不能比父类中被重写的方法的访问权限更低.例如:如果父类的一个方法被声明为public,那么在子 ...

  4. 关于JavaScript设计模式的学习(二)

    第二部分来了,是关于结构型的,同样的,还是在简书中,GitHub上也有代码示例和详细注释 简书:http://www.jianshu.com/p/face1be4b846 github:https:/ ...

  5. phpStorm9.0 +xampp+chrome php调试环境配置!

    不多说,直接上step by step: 1.xampp配置 看看我的XAMPP版本: 修改配置文件,该打开打开,该加上加上,结果如下(当前需要重新启动apache,配置才会生效): [XDebug] ...

  6. WPF调用摄像头

    添加程序集:WPFMediaKit.dll 更关键代码如下: 界面设计代码如下: <Window x:Class="摄像头调用.MainWindow" xmlns=" ...

  7. Eclipse中安装svn的插件安装和使用

    先关闭Eclipse 步骤一:下载site-1.10.11.zip  将其解压 解压后目录 步骤二:创建一个文件夹svn,将解压后的文件copy到svn路径下 步骤三:打开Eclipse安装路径: e ...

  8. 虚函数&&虚继承

    如果说没有虚函数的虚继承只是一个噩梦的话,那么这里就是真正的炼狱.这个C++中最复杂的继承层次在VS上的实现其实我没有完全理解,摸爬滚打了一番也算得出了微软的实现方法吧,至于一些刁钻的实现方式我也想不 ...

  9. java 两个csv文件数据去重

    1.pom.xml配置 <dependency> <groupId>commons-io</groupId> <artifactId>commons-i ...

  10. CPU封装技术介绍

    所谓“CPU封装技术”是一种将集成电路用绝缘的塑料或陶瓷材料打包的技术.以CPU为例,我们实际看到的体积和外观并不是真正的CPU内核的大小和面貌,而是CPU内核等元件经过封装后的产品. CPU封装对于 ...