1. 程式人生 > >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. }

執行結果:

存入 :1000 餘額: 1999.0

取出 :800 餘額: 1198.0

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.     println("一個月的利息為"+interest+"剩餘免費次數"+sa.CurrentCount)
  45.   }
  46. }

執行結果:

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

一個月的利息為: 151.3482 剩餘免費次數: 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. class Bundle() extends Item{
  8.   val itemList=scala.collection.mutable.ArrayBuffer[Item]()
  9.   def addItem(item:Item){
  10.     itemList+=item
  11.   }
  12.   override def price={
  13.     var p:Double=0
  14.     itemList.foreach(i=>p=p+i.price)
  15.     p
  16.   }
  17.   override def description={
  18.     var des=""
  19.     itemList.foreach(i=>des=des+i.description+"")
  20.     des
  21.   }
  22. }
  23. object ItemTest {
  24.   val bundle=new Bundle
  25.   def main(args: Array[String]): Unit = {
  26.     val priceArr=Array(2.5,100,3.5,40,32.5)
  27.     val desArr=Array("鉛筆","水杯","筆記本","火腿腸","滑鼠")
  28.     for(i <- 0 until 5){
  29.       bundle.addItem(new SimpleItem(priceArr(i),desArr(i)))
  30.     }
  31.     println("購物籃資訊如下:")
  32.     bundle.itemList.foreach(item=>println("描述"+item.description+"價格"+item.price))
  33.     println("所購物品如下"+bundle.description)
  34.     println("本次購物合計"+bundle.price+"")
  35.   }
  36. }

執行結果:

購物籃資訊如下:

描述鉛筆價格: 2.5

描述水杯價格: 100.0

描述筆記本價格: 3.5

描述火腿腸價格: 40.0

描述滑鼠價格: 32.5

所購物品如下鉛筆水杯筆記本火腿腸滑鼠

本次購物合計: 178.5

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. class Rectangle(p1: Point, p2: Point, p3: Point) extends Shape {
  5.   override def centerPoint = {
  6.     //
  7.   }
  8. }
  9. class Circle(p1: Point, p2: Point, p3: Point) extends Shape {
  10.   override def centerPoint = {
  11.     //
  12.   }
  13. }

執行結果:

7. 提供一個Square類,擴充套件自java.awt.Rectangle並且有三個構造器:一個以給定的端點和寬度構造正方形,一個以(0,0)為端點和給定的寬度構造正方形,一個以(0,0)為端點、0為寬度構造正方形。

程式程式碼:

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

執行結果:

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 : 檢視常量池

執行結果:Person.scala

執行結果:Person.scala

分析:可以看到兩個類中都有name()方法,但是子類覆寫了父類的。SecretAgent和Person不一樣的是name設定了預設值,用-v檢視,name的secrect實際上是在建構函式中設定的

執行命令:javap -v org.hebut.yu.Person

執行命令:javap -v org.hebut.yu.SecretAgent

 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 )

請解釋protected關鍵字的含義

前一個protected是指主構造器的許可權, 即預設情況下,是不能已傳入elems的方式建立Stack物件的,elems的protected指的是這個引數只有子類才能訪問