【Scala】Scala练习题(二)

【Scala】Scala练习题(二)_第1张图片【Scala】Scala练习题(二)_第2张图片【Scala】Scala练习题(二)_第3张图片

(图片来源于网络,侵删)


一、包和引入

【1】练习使用包的各种声明方式,并查看他们的不同

【2】编写一段程序,将Java哈希映射中的所有元素拷贝到Scala哈希映射。用引入语句重命名这两个类

object Q6 extends App{
  import java.util.{HashMap => JavaHashMap}
  import collection.mutable.{HashMap => ScalaHashMap, Map => ScalaMap}
  val javaMap = new JavaHashMap[Int,String]
  javaMap.put(1, "One");
  javaMap.put(2, "Two");
  javaMap.put(3, "Three");
  javaMap.put(4, "Four");
  val scalaMap = new ScalaHashMap[Int,String]
  for(key <- javaMap.keySet().toArray){
    scalaMap += (key.asInstanceOf[Int] -> javaMap.get(key))
  }
  println(scalaMap.mkString(" "))
}

二、继承

【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}
}

class BankAccount(initialBalance:Double){
  private var balance = initialBalance
  def deposit(amount:Double) = { balance += amount; balance}
  def withdraw(amount:Double) = {balance -= amount; balance}
}
class CheckingAccount(initialBanlance:Double) extends BankAccount(initialBanlance){
  override def deposit(amount:Double) = super.deposit(amount-1)
  override def withdraw(amount:Double) = super.withdraw(amount+1)
}

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

class BankAccount(initialBalance:Double){
  private var balance = initialBalance
  def deposit(amount:Double) = { balance += amount; balance}
  def withdraw(amount:Double) = {balance -= amount; balance}
}
class SavingsAccount(initialBalance:Double) extends BankAccount(initialBalance){
  private var num:Int = _
  def earnMonthlyInterest()={
    num = 3
    super.deposit(1)
  }
  override def deposit(amount: Double): Double = {
    num -= 1
    if(num < 0) super.deposit(amount - 1) else super.deposit(amount)
  }
  override def withdraw(amount: Double): Double = {
    num -= 1
    if (num < 0) super.withdraw(amount + 1) else super.withdraw(amount)
  }
}

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

import collection.mutable.ArrayBuffer
abstract class Item{
  def price():Double
  def description():String
  override def toString():String={
    "description:" + description() + "  price:" + price()
  }
}
class SimpleItem(val price:Double,val description:String) extends Item{
}
class Bundle extends Item{
  val items = new ArrayBuffer[Item]()
  def addItem(item:Item){
    items += item
  }
  def price(): Double = {
    var total = 0d
    items.foreach(total += _.price())
    total
  }
  def description(): String = {
    items.mkString(" ")
  }
}

【4】设计一个Point类,其x和y坐标可以通过构造器提供。提供一个子类LabeledPoint,其构造器接受一个标签值和x,y坐标,比如:new LabeledPoint(“Black Thursday”,1929,230.07)

class Point(x:Double, y:Double)
class LabeledPoint(x:Double, y:Double, tag:String) extends Point(x,y)

【5】定义一个抽象类Shape,一个抽象方法centerPoint,以及该抽象类的子类Rectangle和Circle。为子类提供合适的构造器,并重写centerPoint方法

abstract class Shape{
  def centerPoint()
}
class Rectangle(startX:Int,startY:Int,endX:Int,endY:Int) extends Shape{
  def centerPoint() {}
}
class Circle(x:Int,y:Int,radius:Double) extends Shape{
  def centerPoint() {}
}

【6】提供一个Square类,扩展自java.awt.Rectangle并且是三个构造器:一个以给定的端点和宽度构造正方形,一个以(0,0)为端点和给定的宽度构造正方形,一个以(0,0)为端点,0为宽度构造正方形

import java.awt.{Point, Rectangle}
class Square(point:Point,width:Int) extends Rectangle(point.x,point.y,width,width){
  def this(){
    this(new Point(0,0),0)
  }
  def this(width:Int){
    this(new Point(0,0),width)
  }
}

三、特质

【1】java.awt.Rectangle类有两个很有用的方法translate和grow,但可惜的是像java.awt.geom.Ellipse2D这样的类没有。在Scala中,你可以解决掉这个问题。定义一个RenctangleLike特质,加入具体的translate和grow方法。提供任何你需要用来实现的抽象方法,以便你可以像如下代码这样混入该特质:

val egg = new java.awt.geom.Ellipse2D.Double(5,10,20,30) with RectangleLike
egg.translate(10,-10)
egg.grow(10,20)

import java.awt.geom.Ellipse2D
trait RectangleLike{
  this:Ellipse2D.Double=>
  def translate(x:Double,y:Double){
    this.x = x
    this.y = y
  }
  def grow(x:Double,y:Double){
    this.x += x
    this.y += y
  }
}
object Test extends App{
  val egg = new Ellipse2D.Double(5,10,20,30) with RectangleLike
  println("x = " + egg.getX + " y = " + egg.getY)
  egg.translate(10,-10)
  println("x = " + egg.getX + " y = " + egg.getY)
  egg.grow(10,20)
  println("x = " + egg.getX + " y = " + egg.getY)
}

四、类型参数

【1】定义一个不可变类Pair[T,S], 带一个swap方法,返回组件交换过位置的新对偶

class Pair[T,S](val t:T,val s:S){
  def swap() = new Pair(s,t)
}

【2】定义一个可变类Pair[T],带一个swap方法,交换对偶中组件的位置

class Pair[T](val s:T,val t:T){
  def swap() = new Pair(t,s)
}

【3】给定类Pair[T, S] ,编写一个泛型方法swap,接受对偶作为参数并返回组件交换过位置的新对偶。

class Pair[T,S](val t:T, val s:S){
  def swap[T,S](t:T,s:S) = new Pair(s,t)
}

【4】编写一个泛型方法middle,返回任何Iterable[T]的中间元素。举例来说,middle(“World”)应得到’r’。

def middle[T](iter:Iterable[T]):T={
  val seq = iter.toArray
  seq(seq.length/2)
}

【5】给定可变类Pair[S,T],使用类型约束定义一个swap方法,当类型参数相同时可以被调用。

class Pair[S,T](val s:S, val t:T){
  def swap(implicit env: S =:= T) = new Pair(t,s)
}

五、文件和正则表达式

【1】编写一小段Scala代码,将某个文件中的行倒转顺序(将最后一行作为第一行,依此类推)

val path = "./exercise01.txt"
val file = Source.fromFile(path)
val reverseLines = file.getLines().toArray.reverse
val pw = new PrintWriter(path)
reverseLines.foreach (line => pw.write(line+"\n"))
pw.close()

【2】编写Scala程序打印出某个网页中所有img标签的src属性。使用正则表达式和分组

val pattern = """]+(src\s*=\s*"[^>^"]+")[^>]*>""".r
val source = scala.io.Source.fromURL("http://www.vernonzheng.com","utf-8").mkString
for (pattern(str) <- pattern.findAllIn(source)) println(str)

六、高级类型

【1】实现一个Bug类,对沿着水平线爬行的虫子建模。move方法向当前方向移动,turn方法让虫子转身,show方法打印出当前的位置。让这些方法可以被串接调用。例如:

bugsy.move(4).show().move(6).show().turn().move(5).show()
上述代码应显示4 10 5

package _1801 {
class Bug(var pos: Int = 0) {
  var forword: Int = 1
  def move(up: Int):this.type = {
    pos += forword * up
    this
  }
  def show():this.type = {
    print(pos + " ")
    this
  }
  def turn():this.type = {
    forword = -forword
    this
  }
}
 class Test extends App {
   val bugsy = new Bug
   bugsy.move(4).show().move(6).show().turn().move(5).show()
 }
}

【2】为前一个练习中的Bug类提供一个流利接口,达到能编写如下代码的效果:

bugsy move 4 and show and then move 6 and show turn around move 5 and show

package _1802 {
     //非动词 non-verb
object then
object show
object around
class Bug(var pos: Int = 0) {
  var forword: Int = 1
  def move(num: Int): this.type = { pos += num; this }
  def and(obj: then.type): this.type = this
  def and(obj: show.type): this.type = { print(pos + " "); this}
  def turn(obj: around.type): this.type = { pos = 0; this}
}
class Test extends App {
  val bugsy = new Bug
  bugsy move 4 and show and then move 6 and show turn around move 5 and show
}
}

【3】实现一个方法,接受任何具备如下方法的类的对象和一个处理该对象的函数。

调用该函数,并在完成或有任何异常发生时调用close方法

def close(): Unit
def tryWithClose[T<:{def close():Unit}](obj:T,func: T => Unit)={
  try{
    func(obj)
  }finally {
    obj.close()
  }
}

【4】编写一个函数printValues,带有三个参数f、from和to,打印出所有给定区间范围内的输入值经过f计算后的结果。这里的f应该是任何带有接受Int产出Int的apply方法的对象。例如:

printValues((x: Int) => x*x, 3, 6) //将打印 9 16 25 36
printValues(Array(1, 1, 2, 3, 5, 8, 13, 21, 34, 55), 3, 6) //将打印 3 5 8 13

def printValues(f:{def apply(param:Int):Int}, from:Int, to:Int)={
  for(i <- from to to) {
    print(f.apply(i) + " ")
  }
}
printValues((x: Int) => x*x, 3, 6) //将打印 9 16 25 36
printValues(Array(1, 1, 2, 3, 5, 8, 13, 21, 34, 55), 3, 6) //将打印 3 5 8 13

都看到这里了,点赞评论一下吧!!!

你可能感兴趣的:(Scala,Scala)