Scala入门笔记

这篇博客介绍了Scala的使用,包括简单的流程控制和trait的混入。通过一个有理数构造的例子展示了如何在Scala中利用trait来扩展子类功能,同时解释了trait混入的规则和顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个构建有理数的scala例子

class Rational(n: Int, d: Int) {
  require(d!=0)
  private val g = gcd(n.abs, d.abs)  //最大公约数
  val numer: Int = n / g
  val denom: Int = d / g


  def this(n: Int) = this(n, 1)

  override def toString = numer + "/" + denom

  def add(that: Rational): Rational =
    new Rational(numer*that.denom+that.numer*denom,
      denom * that.denom)

  def +(that: Rational): Rational = add(that)

  def mul(that: Rational): Rational =
    new Rational(numer*that.numer, denom*that.denom)

  def *(that: Rational): Rational = mul(that)

  def sub(that: Rational): Rational = add(new Rational(-that.numer, that.denom))

  def -(that: Rational): Rational = sub(that)

  def div(that: Rational): Rational = mul(new Rational(that.denom, that.numer))

  def /(that: Rational): Rational = div(that)

  private def gcd(a: Int, b: Int): Int =
    if(b == 0) a else gcd(b, a % b)
}

调用:

object test {
  //下面这个函数是为了实现将整数隐式转换为有理数,在有必要的时候。
  implicit def IntToRational(i: Int) = new Rational(i)

  def main(args: Array[String]) {
    val a = new Rational(1,2)
    val b = new Rational(3, 5)
    val c = 2 * b
    println(c)
  }
}

简单的流程控制

val filesHere = (new java.io.File("./src")).listFiles()
for (f <- filesHere if f.getName.endsWith(".scala"))
    println(f)
//下面这句话和上面的其实是等价的!
filesHere.foreach(f => println(if (f.getName.endsWith(".scala")) f))
//也可以对for循环安装多个if过滤
for (f <- filesHere if f.getName.endsWith(".scala"); if f.getName.length > 3)
    println(f)
object test{
  def main(args: Array[String]) {
    val filesHere = (new java.io.File("./src")).listFiles()
    for (f <- filesHere if f.getName.endsWith(".scala"); if f.getName.length > 3)
      println(f)
    filesHere.foreach(f => println(if (f.getName.endsWith(".scala") && f.getName.length > 3) f))

    def fileLines(file: java.io.File) =
      scala.io.Source.fromFile(file).getLines.toList

    def grep(pattern: String) =
      for {
        file <- filesHere  //这个是第一层循环
        if file.getName.endsWith(".scala")
        line <- fileLines(file = file)  //注意这里是第二层循环
        trimmed = line.trim
        if trimmed.matches(pattern)
      } println(file +": " + trimmed)
    grep(".*gcd.*")
  }
}

trait的混入

在scala中,可以通过混入特质来更新子类的行为,但是又不需要修改父类,这样可以轻松的更新功能,下面就演示一个《scala编程》中的例子:

import scala.collection.mutable.ArrayBuffer

/**
  * Created  on 2016/10/5.
  */

abstract class IntQueue{
  def get: Int
  def put(x: Int): Unit
}

trait Doubling extends IntQueue{
  abstract override def put(x: Int): Unit = {super.put(2*x)}
}

trait Increment extends IntQueue{
  abstract override def put(x: Int): Unit = {super.put(x + 1)}
}

trait Filter extends IntQueue{
  abstract override def put(x: Int): Unit = {if(x > 0) super.put(x)}
}

class BasicIntQueue extends IntQueue {
  private val buf = new ArrayBuffer[Int]
  def get = buf.remove(0)
  def put(x: Int) { buf += x }
}

class StandardIntQueue extends BasicIntQueue with Increment with Doubling  with Filter

这里定义了一个抽象类IntQueue,然后定义了一个基类BasicIntQueue,然后定义了三个trait,但是都是extends IntQueue,所以,它们只用用来修饰继承了IntQueue的子类。这里的BasicIntQueue是不能直接用这三个 trait来修饰的。IntQueue是一个抽象类,所以继承类必须实现抽象类的所有方法,如果直接用trait修饰BasicIntQueue,则与BasicIntQueue中的put方法冲突。

object MyInt {
  def main(args: Array[String]): Unit = {
    val sq = new StandardIntQueue
    sq.put(10)
    sq.put(2)
    println(sq.get)
    println(sq.get)
  }
}

另外需要说明的是,多个trait作用时,是最右边的开始起作用,然后从右到左。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值