Scala学习笔记(二)----类

  • 一个源文件中可以包含多个类,并且都可以是public级别。
  • 构造函数分为主构造函数和副构造函数,副构造函数用def this()声明。
  • 继承extends
  • 重写父类方法 override def
  • 重写字段 override val , override var
//主构造器直接跟在类名后面,主构造器中的参数最后会被编译成字段
//主构造器执行时。会执行类中的所有语句
//假设参数声明时不带val和var,相当于private[this]
class Person(var name : String,val age : Int){
    println("this is the primary constructor!")
    var gender : String = _
    val school = "ZJU"

    //附属构造器名称为this
    //每个附属构造器必须首先调用已经存在的主构造器,或者附属构造器
    def this(name : String, age : Int, gender : String){
      this(name,age)
      this.gender = gender
    }
}

class Student(name : String , age : Int,val major : String) extends Person(name,age){
  println("this is the subclass of Person , major is : "+major)

  override val school = "BJU"
  override def toString = "override toString..."
}

object WeekTwo {

  def main(args : Array[String]){
     //val p = new Person("Jack",20,"male")
     //p.name = "Jack"
     //println(p.name+" : "+p.age+" : "+p.gender )
    val s = new Student("Justin",20,"Math")
    println(s.toString)
    }
}

抽象类

  • 由abstract修饰的类
  • 类的一个或者多个方法没有完整的定义
  • 声明抽象方法不需要加abstract关键字,只需要不写方法体
  • 子类重写父类的抽象方法时不需要加override
  • 父类可以声明抽象字段,即没有初始值的字段
  • 子类重写父类的抽象字段时不需要加override
abstract class Person1{
  def speak
  val name : String
  var age : Int
}

class Student1 extends Person1{
  def speak {
    println("speak!!!")
  }

  val name = "AAA"
  var age = 100

}

特质trait----对比java的接口

  • trait可以看作是一个可以带有具体实现的接口
  • 字段和行为的集合
  • 通过with关键字,一个类可以扩展多个trait
  • 也可以为某个特定的对象指定trait
  • trait是从左到右被构造的
trait ConsoleLogger{
  def log(msg : String){
    println("save money : "+msg)
  }
}

trait MessageLogger extends ConsoleLogger{
 override def log(msg : String){
    println("save money to bank : "+msg)
  }
}

abstract class Account{
  def save
}

class MyAccount extends Account with ConsoleLogger{
  def save{
    log("100")
  }
}

object Basic extends App{

  val acc = new MyAccount with MessageLogger
  acc.save
  //save money to bank : 100
  val acc2 = new MyAccount
  acc2.save
  //save money : 100

apply方法和单例对象

scala风格的创建对象就是定义和使用 object的apply方法,apply方法返回伴生类的对象,为什么不用构造器呢,对于嵌套表达式而言,省去new关键字会方便很多。 放在object中的所有方法可以看做是这个类的静态方法,scala没有static关键字,等效的做法是把方法定义在object里。

  • 类名后面加括号调用的是object的apply方法
val a = ApplyTest()
  • 对象后面加括号调用的是类的apply方法
val t = new ApplyTest
t()
class ApplyTest{
  def apply() = "Apply"
  def test{
    println("test")
  }
}

object ApplyTest{
  def apply() = new ApplyTest

  var count = 0 
  def incr = {
    count = count+1
  }

  def static{
    println("I am not a static method")
  }
}

object Basic4 extends App{
 // ApplyTest.static
  //val a = ApplyTest()
  //a.test
 // val t = new ApplyTest
  //println(t())
  //println(t)

  for (i <- 1 to 10){
    ApplyTest.incr
  }
  println(ApplyTest.count )

}

class Person3(name : String) {
    val _name = name.split("\\s+")
    val firstName = _name(0)
    val secondName = _name(1)
    override def toString() = s"His first name is $firstName , and his second nane is $secondName."
}

object Person3{

  def apply(name : String) = new Person3(name)
  def main(args : Array[String]){
    val a = new Person3("Xue  Chao")//传统的构造方法,但不是scala风格
    val b = Person3("Xue Chao")//类名后面加括号调用的是object的apply方法
    println(a)
    println(b)
  }  
}

object可以模拟static,也可以模拟单例对象,它就代表它自己。

模式匹配

  • 标准用法match
  • 使用守卫 _
  • 匹配类型
val result = value match{
    case i if i == 1 => "one"
    case i if i == 2 => "two"
    case _ => "some other number"
  } 
  println("result of match is : "+result)

  def t (obj : Any) = obj match{
    case x : Int => println("Int")
    case s : String => println("String")
    case _ => println("unknown type")      
  }

case class(多用在模式匹配中)

  • 构造器中的每个类型都为val,不建议用var。
  • 不用new就可以直接产生对象,因为编译器会根据case关键字自动生成apply方法。
object CaseClassDemo extends App{

  val m = Map(1->2)
  m.get(10) match {
    case Some(v) => println(v)
    case None => println("No such key")
  }

    def m(p : Person){
        p match {
        case Teacher(_) => println("This is a teacher")
        //case Teacher("Peter") => println("This is teacher Peter")
        case Student(_) => println("This is a student")
        case _ => println("This is unknown")
      }
    }

    m(Student("A"))
}

abstract class Person

case class Teacher(name : String) extends Person

case class Student(name : String) extends Person

文件访问

  • 按行读取 getLines()
  • 按字符读取直接用文件句柄,不getLine()
  • 从网络读取
import scala.io.Source
val file = Source.fromFile("D:/code/scala/week2/data.txt")
//val file = Source.fromURL("http://www.baidu.com")
for(line <- file.getLines()){
//for(line <- file){ //按字符读取
    println(line)
  }

option做模式匹配

option有两个子类:Some和None.如匹配到有值,为Some类型,如果没有匹配到值,返回None类型

 val m = Map(1->2)
  m.get(10) match {
    case Some(v) => println(v)
    case None => println("No such key")
  }
 10会输出No such key
 1会输出1

String interpolation变量内插

 val a = "Xuechao"
 val b = "Tangbo"
 println(s"$a love $b")
 //输出 Xuechao love Tangbo

Comments !