Scala学习(八)练习

 Scala中继承&练习

1. 扩展如下的BankAccount类，新类CheckingAccount对每次存款和取款都收取1美元的手续费

class BankAccount ( initialBalance: Double) {

private var balance = initialBalance

def deposit (amount: Double) = { balance += amount; balance }

def withdraw(amount: Double)={ balance -= amount; balance }

}

1. class BankAccount(initialBalance:Double){
2.   private var balance=initialBalance
3.   def deposit(amount:Double)={
4.     balance+=amount
5.     balance
6.   }
7.   def withdraw(amount:Double)={
8.     balance-=amount
9.     balance
10.   }
11.   def currentBalance=balance
12. }
13. //一种实现
14. class checkingAccount (initialBalance:Double) extends BankAccount(initialBalance){
15.   override def deposit(amount:Double)={
16.     super.deposit(amount-1)
17.   }
18.   override def withdraw(amount:Double)={
19.     super.withdraw(amount+1)
20.   }
21. }
22. object checkingAccount{
23.   val cha=new checkingAccount(1000)
24.   val dbal=1000
25.   val wbal=800
26.   def main(args: Array[String]): Unit = {
27.     cha.deposit(dbal)
28.     println("存入 :"+dbal+"余额: "+cha.currentBalance)
29.     cha.withdraw(wbal)
30.     println("取出 :"+wbal+"余额: "+cha.currentBalance)
31.   }
32. }

2. 扩展前一个练习的BankAccount类，新类SavingsAccount每个月都有利息产生( earnMonthlylnterest方法被调用 )，并且有每月三次免手续费的存款或取款。在eamMonthlylnterest方法中重置交易计数

1. class SavingsAccount(initialBalance:Double) extends BankAccount(initialBalance){
2.   private var freeCount=3
3.   private val interestRate=0.03
4.   def CurrentCount = freeCount
5.   def earnMonthlyInterrest:Double={
6.     freeCount=3
7.     super.deposit(super.deposit(0)*interestRate)
8.     super.deposit(0)*interestRate
9.   }
10.   override def deposit(amount:Double):Double={
11.     if(freeCount>0){
12.       freeCount-=1
13.       super.deposit(amount)
14.     }else{
15.       super.deposit(amount-1)
16.     }
17.   }
18.   override def withdraw(amount:Double):Double={
19.     if(freeCount>0){
20.       freeCount-=1
21.       super.withdraw(amount)
22.     }else{
23.       super.withdraw(amount+1)
24.     }
25.   }
26. }
27. object SaveTest{
28.   val dbal=1000
29.   val wbal=100
30.   var interest=0.0
31.   val sa=new SavingsAccount(1000)
32.   def main(args: Array[String]): Unit = {
33.     for(i<- 1 to 32){
34.       if(i>=1&& i<=4){
35.         sa.deposit(1000)
36.         println(i+"号存入: "+dbal+"余额: "+sa.currentBalance+"剩余免费次数: "+sa.CurrentCount)
37.       }else if(i>=29&&i<=31){
38.         if(i==30)
39.           interest=sa.earnMonthlyInterrest
40.         sa.withdraw(100)
41.         println(i+"号取出: "+wbal+"余额: "+sa.currentBalance+"剩余免费次数: "+sa.CurrentCount)
42.
43.       }
44.     }
45.     println("一个月的利息为: "+interest+"剩余免费次数: "+sa.CurrentCount)
46.   }
47. }

1号存入: 1000余额: 2000.0 剩余免费次数: 2

2号存入: 1000余额: 3000.0 剩余免费次数: 1

3号存入: 1000余额: 4000.0 剩余免费次数: 0

4号存入: 1000余额: 4999.0 剩余免费次数: 0

29号取出: 100余额: 4898.0 剩余免费次数: 0

30号取出: 100余额: 4944.94 剩余免费次数: 2

31号取出: 100余额: 4844.94 剩余免费次数: 1

3. 翻开你喜欢的Java或C++教科书，一定会找到用来讲解继承层级的示例，可能是员工、宠物、图形或类似的东西，用Scala来实现这个示例

1. abstract class Animal{
2.   def run
3. }
4. class Cat extends Animal{
5.   override def run=println("I can run,miao!")
6. }
7. class Dog extends Animal{
8.   override def run=println("I can run,wang!")
9. }
10. object AnimalTest {
11.   def main(args: Array[String]): Unit = {
12.     val cat=new Cat
13.     val dog=new Dog
14.     cat.run
15.     dog.run
16.   }
17. }

I can run,miao!

I can run,wang!

4. 定义一个抽象类ltem，加入方法price和description。Simpleltem是一个在构造器中给出价格和描述的物件。利用val可以重写def这个事实。Bundle是一个可以包含其他物件的物件。其价格是打包中所有物件的价格之和。同时提供一个将物件添加到打包当中的机制，以及一个合适的description方法

1. abstract class Item{
2.   def price:Double
3.   def description:String
4. }
5. class SimpleItem(override val price:Double,override val description:String) extends Item{
6. }
7.
8. class Bundle() extends Item{
9.   val itemList=scala.collection.mutable.ArrayBuffer[Item]()
11.     itemList+=item
12.   }
13.   override def price={
14.     var p:Double=0
15.     itemList.foreach(i=>p=p+i.price)
16.     p
17.   }
18.   override def description={
19.     var des=""
20.     itemList.foreach(i=>des=des+i.description+"")
21.     des
22.   }
23. }
24. object ItemTest {
25.   val bundle=new Bundle
26.   def main(args: Array[String]): Unit = {
27.     val priceArr=Array(2.5,100,3.5,40,32.5)
28.     val desArr=Array("铅笔","水杯","笔记本","火腿肠","鼠标")
29.     for(i <- 0 until 5){
31.     }
32.     println("购物篮信息如下:")
33.     bundle.itemList.foreach(item=>println("描述: "+item.description+"价格: "+item.price))
34.     println("所购物品如下: "+bundle.description)
35.     println("本次购物合计: "+bundle.price+"")
36.   }
37. }

5. 设计一个Point类，其x和y坐标可以通过构造器提供。提供一个子类LabeledPoint，其构造器接受一个标签值和x、y坐标，比如：

new LabeledPoint("Black Thursday", 1929, 230.07)

1. class Point(val x:Double,val y:Double) {
2.   override def toString="x= "+x+" y= "+y
3. }
4. class LabelPoint(val label:String,override val x:Double,override val y:Double)extends Point(x,y){
5.   override def toString ="label= "+label+"x= "+x+"y= "+y
6. }
7. object PointTest{
8.   def main(args: Array[String]): Unit = {
9.     val point=new Point(2,3)
10.     val lpoint=new LabelPoint("圆形",2,3)
11.     println(point)
12.     println(lpoint)
13.   }
14. }

x= 2.0 y= 3.0

label= 圆形 x= 2.0y= 3.0

6. 定义一个抽象类Shape、一个抽象方法centerPoint，以及该抽象类的子类Rectangle和Circle。为子类提供合适的构造器，并重写centerPoint方法

1. abstract class Shape {
2.   abstract def centerPoint: Point
3. }
4.
5. class Rectangle(p1: Point, p2: Point, p3: Point) extends Shape {
6.   override def centerPoint = {
7.     //
8.   }
9. }
10.
11. class Circle(p1: Point, p2: Point, p3: Point) extends Shape {
12.   override def centerPoint = {
13.     //
14.   }
15. }

7. 提供一个Square类，扩展自java.awt.Rectangle并且有三个构造器：一个以给定的端点和宽度构造正方形，一个以(0，0)为端点和给定的宽度构造正方形，一个以(0，0)为端点、0为宽度构造正方形。

1. import java.awt.Point
2. import java.awt.Rectangle
3.
4. class Squre extends Rectangle{
5.   height=0
6.   width=0
7.   x=0
8.   y=0
9.   def this(p:Point,w:Int){
10.     this()
11.     this.height=w
12.     this.width=w
13.     this.x=p.x
14.     this.y=p.y
15.   }
16.   def this(width:Int){
17.     this(new Point(0,0),width)
18.   }
19. }
20. object SqureTest {
21.   def main(args: Array[String]): Unit = {
22.     val rect1=new Squre()
23.     val rect2=new Squre(2)
24.     val rect3=new Squre(new Point(2,3),5)
25.     println(rect1)
26.     println(rect2)
27.     println(rect3)
28.   }
29. }

org.hebut.yu.two.Squre[x=0,y=0,width=0,height=0]

org.hebut.yu.two.Squre[x=0,y=0,width=2,height=2]

org.hebut.yu.two.Squre[x=2,y=3,width=5,height=5]

8. 编译的Person和SecretAgent类并使用javap分析类文件。总共有多少name的getter方法，它们分别取什么值

class Person ( val name: String ) {

override def toString=getClass.getName+"name="+ name+ "]"

}

class SecretAgent (codename: String) extends Person (codename) {

override val name = "secret" // 不想暴露真名…

override val toString = "secret" // …或类名

}

javap -p : 查看编译的内容

javap -c : 查看想详细操作指令

javap -v : 查看常量池

9. 在Creature类中，将val range替换成val def。如果你在Ant子类中也用def的话会有什么效果，如果在子类中使用val又会有什么效果，为什么

class Creature {

val range : Int=10

val env: Array[Int] = new Array[Int] ( range)

}

class Ant extends Creature {

override val range=2

}

class Ant extends {

override val range=2

} with Creature

def覆写def子类的env可以正确初始化而用val覆写defenv会被初始化成0长度。这个跟val覆写val的道理是一样的。父类和子类同时存在私有的同名变量range和相同的range的getter，但是父类构造函数先被调用，却在其中调用子类的getter。因为父类 的getter以被子类覆写。子类的range因为此时还没初始化，所以返回了0。父类构造函数，错误地使用0来初始化了env。这种行为本身就是个坑，但是也提供了非常大的灵活性。面向对象的Template设计模式就依赖这种行为实现的，所以还是多多善用为妙。

10. 文件scala/collection/immutable/Stack.scala包含l如下定义：

class Stack[A] protected ( protected val elems: List[Al )

posted @ 2015-07-01 15:07 sunddenly 阅读(...) 评论(...) 编辑 收藏