Scala By Example: 类和对象

累……哦,不对,是类

   1: // If class A extends class B, we say that type A 'conforms' to type B. If a
   2: // class does not mention a supperclass in its definition, the root type
   3: // scala.AnyRef (an alias for java.lang.Object) is implicitly assumed.
   4: class Rational(n: Int, d: Int) {
   5:     private def gcd(x: Int, y: Int): Int = {
   6:         if(x == 0) y
   7:         else if(x < 0) gcd(-x, y)
   8:         else if(y < 0) -gcd(x, -y)
   9:         else gcd(y % x, x)
  10:     }
  11:     private val g = gcd(n, d)
  12:  
  13:     val numer: Int = n / g
  14:     val denom: Int = d / g
  15:     def +(that: Rational) =
  16:         new Rational(numer * that.denom + that.numer * denom,
  17:             denom * that.denom)
  18:     def -(that: Rational) =
  19:         new Rational(numer * that.denom - that.numer * denom,
  20:             denom * that.denom)
  21:     def *(that: Rational) =
  22:         new Rational(number * that.numer, denom * that.denom)
  23:     def /(that: Rational) =
  24:         new Rational(number * that.denom, denom * that.numer)
  25:  
  26:     // Unlike in Java, methods in Scala do not necessarily take a parameter
  27:     // list, but can be invoked by simply mentioning its name
  28:     def square = new Rational(numer * numer, denom * denom)
  29:  
  30:     // Note that, unlike in Java, redefining definitions need to be preceded by
  31:     // an 'override' modifier.
  32:     override def toString = "" + numer + "/" + denom
  33: }

一个表示有理数的类(开始怀念小学时的数学组了 T_T)。在单根体系中,所有的类都继承自同一超类,在 Java 中是 Object,在 Scala 中是 AnyRef,当然,你可以在两者间画个等号。与 Java 不同的是,首先在 Scala 里,方法不一定需要参数列表(见 square)。实际上,无参数方法(parameterless method)的调用和值(value field)形式上是完全相同的。两者的不同点在于,对于 value field 而言,其等号右边的表达式会在创建对象的时候进行求值并且从此保持不变(仅右操作数的值不变!不是说 value field);无参数方法则在每次调用的时候都会进行求值。这样做的好处是,当某天你需要把一个 value field 重构成计算值(computed value)时,直接改就可以,调用这个值的代码无需做任何修改。(参考在 Groovy 中的基于 JavaBean 命名方式的另一种解决方案,当你写一个 getX() 方法时,你可以通过 x 的方式像调用一个值一样调用方法,即使 x 本身存在于类定义内)。另一个和 Java 的差异则是覆写超类成员的方法。在 Java 中,你有可能在试图覆写超类时由于拼写错误而创造一个新的发法,对此编译器将无能为力(小小提示:打开你的 @Override 注释)。而在 Scala 中,由于必须加上 override 修饰符,事情就变得简单了。

在代码 15 ~ 24 行,可以看到代表了四则运算的四个函数,事实上,这并非“运算符重载”,而只是普通的方法而已。

最后我们在代码中也看到了熟悉的 private 修饰符。在 Scala 中,访问控制修饰符的应用远比 Java 来的细致(抑或复杂),但眼下,让我们略过这些,简单飘过。(按我的经验,在多数日常任务中,Scala 或 Groovy 的基本权限控制就很不错了,但写类库给别人用时确实要注意!还有就是,当你面对 Groovy 强大的元编程力量时,你究竟能不能控制住还是个问题)

补充:在铅笔书的第四章提到了非常重要的一点:只有主构造函数才能向基类构造函数中传递参数

抽象累……类
   1: trait IntSet {
   2:     def incl(x: Int): IntSet
   3:     def contains(x: Int): Boolean
   4: }
   5:  
   6: object EmptySet extends IntSet {
   7:     def contains(x: Int) = false
   8:     def incl(x: Int): IntSet = new NonEmptySet(x, this, this)
   9: }
  10:  
  11: class NonEmptySet(elem: Int, left: IntSet, right: IntSet) extends IntSet {
  12:     def contains(x: Int) =
  13:         if(x < elem) left contains x
  14:         else if(x > elem) right contains x
  15:         else true
  16:     def incl(x: Int): IntSet =
  17:         if(x < elem) new NonEmptySet(elem, left incl x, right)
  18:         else if(x > elem) new NonEmptySet(elem, left, right incl x)
  19:         else this
  20: }

在 Scala 中抽象类和 Java 是一样的。在以上二叉树代码中,我用 trait 关键字代替了 abstract class,你可以把它直接替换回来。但是注意,trait 并不等同于抽象类,在以后的示例中我们会看到 trait 其实更像拥有实现代码的接口,依赖 trait 的 mix-in 机制,可以解决很多多重继承的问题。

在第二行,我们看到了 object 关键字。EmptySet 是一个(单例)对象,Scala 没有 static,也不需要仅仅为了访问一个(静态)量而创建一个类。在第 8 行,更清晰的写法是用 EmptySet 来代替 this (见仁见智?)。当然,单例在编译后就是一个使用静态方法的 Java 类,同理,仅仅在第一次调用其值时,jvm 才会实际生成这个对象(lazy evaluation)。

习题 1: 向二叉树添加 union 和 intersection 函数

习题 2: 添加 excl(x: Int) 函数来排除某个元素(顺便加上 isEmpty 函数)

基础型别(依稀记得侯捷老师好像是这么翻译 primitive type 的)和类

在 Scala 的语法层面,万事皆类,基础型别亦然(它们其实是 Scala 的 Predef 模块中类的别名,如 type int = scala.Int)。但是在具体实现层面,编译器会在适当的场合使用基础型别。可以这么说,基础型别仅仅是“优化措施”而已(相对的,在 Java 中则是重要的语法元素)。没有基础型别,Scala 依然可以完成所有任务!以下来看一个没有基础型别的自然数实现:

   1: abstract class Nat {
   2:     def isZero: Boolean
   3:     def predecessor: Nat
   4:     def successor: Nat
   5:     def + (that: Nat): Nat
   6:     def - (that: Nat): Nat
   7: }
   8:  
   9: object Zero extends Nat {
  10:     def isZero = true
  11:     // how to throw out an Error exception
  12:     def predecessor: Nat = error("negative number")
  13:     def successor: Nat = new Succ(Zero)
  14:     def + (that: Nat) = that
  15:     def - (that: Nat): Nat =
  16:         if(that.isZero) Zero
  17:         else error("negative number")
  18: }
  19:  
  20: // a lot of recursive calls
  21: class Succ(x: Nat) extends Nat {
  22:     def isZero = false
  23:     def predecessor = x
  24:     def successor: Nat = new Succ(this)
  25:     def + (that: Nat): Nat = x + that.successor
  26:     def - (that: Nat): Nat =
  27:         if(that.isZero) this
  28:         else x - that.predecessor
  29: }
  30:  
  31: val one = new Succ(Zero)
  32: val two = new Succ(one)
  33: val three = new Succ(two)
  34:  
  35: println((three - two - one).isZero)
  36:  
  37: // will throw Error exception!
  38: // one - two

注意到一旦开始使用 Scala 你会多么频繁的使用递归!当然,注意 Scala 是如何抛出一个 Error 异常的。

习题 3:不依靠 Scala 的数字类或基础型别实现 Integer 类,包含 Nat 的所有方法,并加上 isPositive 函数和 negate 函数。

PS. 这一章看完学到很多数学方面的单词……

PS II. 又冷又累又饿:又降温了,怎么穿都不热(少穿两件也不觉得更冷);又思考了,怎么睡都不醒(少眯两个钟头也不会更困);又发育了,怎么吃都不饱(少吃两斤大米也没见得更瘦)

Technorati 标签: Scala
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 Introduction 1 2 A First Example 3 3 Programming with Actors and Messages 7 4 Expressions and Simple Functions 11 4.1 Expressions And Simple Functions . . . . . . . . . . . . . . . . . . . . . . 11 4.2 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 4.3 Conditional Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 4.4 Example: Square Roots by Newton’s Method . . . . . . . . . . . . . . . . 15 4.5 Nested Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 4.6 Tail Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 5 First-Class Functions 21 5.1 Anonymous Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 5.2 Currying . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 5.3 Example: Finding Fixed Points of Functions . . . . . . . . . . . . . . . . 25 5.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 5.5 Language Elements Seen So Far . . . . . . . . . . . . . . . . . . . . . . . 28 6 Classes and Objects 31 7 Case Classes and Pattern Matching 43 7.1 Case Classes and Case Objects . . . . . . . . . . . . . . . . . . . . . . . . 46 7.2 Pattern Matching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 8 Generic Types and Methods 51 8.1 Type Parameter Bounds . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 8.2 Variance Annotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56iv CONTENTS 8.3 Lower Bounds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 8.4 Least Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 8.5 Tuples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 8.6 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 9 Lists 63 9.1 Using Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 9.2 Definition of class List I: First Order Methods . . . . . . . . . . . . . . . 65 9.3 Example: Merge sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 9.4 Definition of class List II: Higher-Order Methods . . . . . . . . . . . . . 70 9.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 10 For-Comprehensions 79 10.1 The N-Queens Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 10.2 Querying with For-Comprehensions . . . . . . . . . . . . . . . . . . . . . 81 10.3 Translation of For-Comprehensions . . . . . . . . . . . . . . . . . . . . . 82 10.4 For-Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 10.5 Generalizing For . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 11 Mutable State 87 11.1 Stateful Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 11.2 Imperative Control Structures . . . . . . . . . . . . . . . . . . . . . . . . . 91 11.3 Extended Example: Discrete Event Simulation . . . . . . . . . . . . . . . 92 11.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 12 Computing with Streams 99 13 Iterators 103 13.1 Iterator Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 13.2 Constructing Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 13.3 Using Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
1 Introduction 1 2 A First Example 3 3 Programming with Actors andMessages 7 4 Expressions and Simple Functions 11 4.1 Expressions And Simple Functions . . . . . . . . . . . . . . . . . . . . . . 11 4.2 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 4.3 Conditional Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 4.4 Example: Square Roots by Newton’sMethod . . . . . . . . . . . . . . . . 15 4.5 Nested Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 4.6 Tail Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 5 First-Class Functions 21 5.1 Anonymous Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 5.2 Currying . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 5.3 Example: Finding Fixed Points of Functions . . . . . . . . . . . . . . . . 25 5.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 5.5 Language Elements Seen So Far . . . . . . . . . . . . . . . . . . . . . . . 28 6 Classes and Objects 31 7 Case Classes and PatternMatching 43 7.1 Case Classes and Case Objects . . . . . . . . . . . . . . . . . . . . . . . . 46 7.2 PatternMatching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 8 Generic Types andMethods 51 8.1 Type Parameter Bounds . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 8.2 Variance Annotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 8.3 Lower Bounds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 8.4 Least Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 8.5 Tuples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 8.6 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Lists 63 9.1 Using Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 9.2 Definition of class List I: First OrderMethods . . . . . . . . . . . . . . . 65 9.3 Example: Merge sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 9.4 Definition of class List II: Higher-OrderMethods . . . . . . . . . . . . . 70 9.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 0 For-Comprehensions 79 10.1 The N-Queens Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 10.2 Querying with For-Comprehensions . . . . . . . . . . . . . . . . . . . . . 81 10.3 Translation of For-Comprehensions . . . . . . . . . . . . . . . . . . . . . 82 10.4 For-Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 10.5 Generalizing For . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 1 Mutable State 87 11.1 Stateful Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 11.2 Imperative Control Structures . . . . . . . . . . . . . . . . . . . . . . . . . 91 11.3 Extended Example: Discrete Event Simulation . . . . . . . . . . . . . . . 92 11.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 2 Computing with Streams 99 3 Iterators 103 13.1 IteratorMethods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 13.2 Constructing Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 13.3 Using Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 4 Lazy Values 109 5 Implicit Parameters and Conversions 113

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值