Scala类的定义,主/辅构造器,以及方法中的变量定义,单例对象,伴生对象,Apply方法调用,应用程序对象

1. 类

1.1. 类的定义

package cn.toto.scala.day2

/**
  * 在Scala中,类并不用声明为public类型的。
  * Scala源文件中可以包含多个类,所有这些类都具有共有可见性。
  * Created by toto on 2017/6/29.
  */
class Person {
  //用val修饰的变量是可读属性,有getter但没有setter(相当与Java中用final修饰的变量)
  val id = "9527"

  //用var修饰的变量都既有getter,又有setter
  var age : Int = 18

  //类私有字段,只能在类的内部使用
  private var name : String = "toto"

  //对象私有字段,访问权限更加严格的,Person类的方法只能访问到当前对象的字段
  //在伴生对象里面也不可以访问,这里相当于是java中private的,没有getter和setter的方法
  private[this] var pet = "小强"

  def sayHi() : Unit = {
    //下面的运行结果是:9527
    println(id)
    //下面的结果是:18
    println(age)
    //说明在自己的类中可以访问到,下面的运行结果是:toto
    println(name)
    //说明只有在类里面可以访问到private[this]类型的变量,下面的运行结果是"小强",说明已经被修改了。
    println(pet)
  }
}

/**
  * 这个名字和类名相同,叫伴生对象
  */
object Person {
  //在伴生变量中定义的变量相当于就是静态变量
  var i = 1

  //在伴生变量中定义的方法相当于是静态方法

  def main(args: Array[String]): Unit = {
    //结果是:1
    println(i)

    val p = new Person()
    //如果是下面的修改,发现下面有红线,说明val类型的不支持重新赋值
    //p.id = "123"
    //下面的结果是:9527
    println(p.id)
    //下面的结果是:18
    println(p.age)
    p.age = 27
    //下面的结果是:27
    println(p.age)
    //下面的结果是:唐伯虎
    println(p.name)
    p.name = "toto"
    //这里说明可以在伴生对象中访问到私有的变量
    //下面的结果是:toto
    println(p.name)
    p.sayHi()
  }
}

object Test {
  def main(args: Array[String]): Unit = {
    var p = new Person()
    //运行结果是18
    println(p.age)
    //运行结果是:9527
    println(p.id)
    /**
      * 下面的运行结果是:
      * 9527
      * 18
      * 唐伯虎
      * 小强
      */
    p.sayHi()
    //这里不可以直接通过p.pet访问到。
    //这里面也不可以访问到p.name
  }
}

1.2. 构造器

注意:主构造器会执行类定义中的所有语句

package cn.toto.scala.day2

import java.io.IOException

/**
  * Created by toto on 2017/6/29.
  *
  * 构造器参数可以不带val或var,如果不带val或var的参数至少被一个方法所使用
  * 那么它将被提升为字段
  *
  * 跟类名交织在一起的叫   主构造器
  * val定义的只能读不能改(成员变量)
  * var 可以读,有了默认值,在传参的时候,可以不传参了。
  * faceValue :可以通过这个为它初始赋值,有了默认值,可以不传参了,相当于private[this],只能在类的内部使用
  */
class Student(val name : String,
              var age:Int,
              faceValue:Double = 99.9,
              private var height : Int = 18) {

  //主构造器会执行类定义中的所有语句
  println("执行主构造器")

  //faceValue被下面的方法使用后,faceValue就变成了不可变的对象私有字段了,等同于private[this] val faceValue
  //如果没有被方法使用该参数将不被保存为字段,仅仅是一个可以被主构造器中的代码访问的普通参数
  def description = name + " is " + age + " years old,颜值是:" + faceValue

  //定义为辅构造函数用
  private[this] var gender : String = null

  try {
    println("读取文件");
    throw new IOException("io exception");
  } catch {
    case e:NullPointerException => println("打印异常Exception:" + e)
    case e:IOException => println("打印异常Exception:" + e)
  }

  def show() : Unit = {
    //faceValue = 1000
    println(faceValue)
  }

  //用this关键字定义辅助构造器
  //辅助构造器 def this (参数)
  def this(name : String,age : Int,gender: String) {
    //每个辅助构造器必须以主构造器或其他的辅助构造器的调用开始
    //第一行必须先调用主构造器
    this(name,age)
    println("执行辅助构造器")
    println("faceValue:" + this.faceValue)
    println("height:" + this.height)
    //对于没法在主构造器中定义的变量,可以定义一个私有字段
    this.gender = gender
    println("gender:" + this.gender)
  }
}

object Student {
  def main(args: Array[String]): Unit = {
    /**
      * 私有的构造器,只有在其伴生对象中使用
      *
      * 下面立即执行出结果:
      * 执行主构造器
      * 读取文件
      * 打印异常Exception:java.io.IOException: io exception
      */
    val p = new Student("toto", 27, 100, 180)
    //运行结果是:27
    println(p.age)
    //运行结果是:toto
    println(p.name)
    p.age = 18
    p.height = 199;
    //运行结果是:18
    println(p.age)
    //运行结果是:199
    println(p.height)

    //运行对的结果是:toto is 18 years old,颜值是:100.0
    println(p.description)

    var per = new Person
    println(per)
  }
}

object Main {
  def main(args: Array[String]): Unit = {
    /**
      * 理解执行出结果:
      * 执行主构造器
      * 读取文件
      * 打印异常Exception:java.io.IOException: io exception
      */
    val stu1 = new Student("toto",30)
    //只是:toto,说明调用的不是辅助构造器
    println(stu1.name)

    /**
      * 调用的时候就立即显示:
      * 执行主构造器
      * 读取文件
      * 打印异常Exception:java.io.IOException: io exception
      * 执行辅助构造器
      * faceValue:99.9
      * height:18
      * gender:男
      */
    var stu2 = new Student("toto",27,"男")
    println(stu2.age)
    println(stu2.name)
    //下面的取不到
    //println(stu2.height)
    //下面的也获取不到
    //println(faceValue);
  }
}

1.3. 单例对象

在Scala中没有静态方法和静态字段,但是可以使用object这个语法结构来达到同样的目的
1.存放工具方法和常量
2.高效共享单个不可变的实例
3.单例模式

package cn.toto.scala.day2

import scala.collection.mutable.ArrayBuffer

object SingletonDemo {
  def main(args: Array[String]) {
    //单例对象,不需要new,用【类名.方法】调用对象中的方法
    val session = SessionFactory.getSession()
    //获得结果:cn.toto.scala.day2.Session@96532d6
    println(session)
  }
}

object SessionFactory {
  //该部分相当于java中静态块
  var counts = 5
  val sessions = new ArrayBuffer[Session]()
  while(counts > 0) {
    sessions += new Session
    counts -= 1
  }

  //在object中的方法相当于java中的静态方法
  def getSession() : Session = {
    sessions.remove(0)
  }
}

class Session {}

在如:

package cn.toto.scala.day2

/**
  * Created by toto on 2017/6/29.
  */
class SingletonDemo2 {

  println("abc")
  SingletonDemo2.sayHi()
  SingletonDemo2

  test()

  def test() : Unit = {
    println("test")
  }
}

object SingletonDemo2 {
  private val t = 123

  def sayHi() : Unit = {
    println("hi ~")
  }

  /**
    * 运行的结果是:
    * hi ~
    * 123
    * 123
    * abc
    * hi ~
    * test
    * hi ~
    * ()
    * cn.toto.scala.day2.SingletonDemo2$@5e025e70
    * cn.toto.scala.day2.SingletonDemo2$@5e025e70
    * cn.toto.scala.day2.SingletonDemo2$@5e025e70
    */
  def main(args: Array[String]): Unit = {
    sayHi()
    println("123")
    println(t)

    val s = new SingletonDemo2

    val s1 = SingletonDemo2.sayHi()
    println(s1)

    val s2 = SingletonDemo2
    val s3 = SingletonDemo2
    println(s3)
    println(s3)
    val s4 = SingletonDemo2
    println(s4)
  }
}

1.4. 伴生对象

在Scala的类中,与类名相同的对象叫做伴生对象,类和伴生对象之间可以相互访问私有的方法和属性

package cn.toto.scala.day2

/**
  * Created by toto on 2017/6/29.
  */
class Dog {
  val id = 1
  private var name = "toto"

  def printName() : Unit = {
    //在Dog类中可以访问伴生对象Dog的私有属性
    println(Dog.CONSTANT + name)
  }
}

object Dog {
  //伴生对象中的私有属性
  private val CONSTANT = "汪汪汪 : "

  /**
    * 运行结果是:
    * 汪汪汪 : toto
    * 汪汪汪 : 123
    * @param args
    */
  def main(args:Array[String]): Unit = {
    val p = new Dog
    //访问私有字段name
    p.printName()

    p.name = "123"
    p.printName()
  }
}

1.5. apply方法

通常我们会在类的伴生对象中定义apply方法,当遇到类名(参数1,…参数n)时apply方法会被调用

package cn.toto.scala.day2

/**
  * Created by toto on 2017/6/30.
  */
object ApplyDemo {
  def main(args: Array[String]): Unit = {
    //調用了Array半生对象的apply方法
    //def apply(x:Int,xs:Int*):Array[Int]
    //arr1中只有一个元素5
    var arr1  = Array(5)
    println(arr1.toBuffer)

    //new了一个长度为5的array,数组里面包含5个null
    var arr2 = new Array(5)
  }
}

在如:

package cn.toto.scala.day2

/**
  * Created by toto on 2017/6/30.
  */
object ApplyDemo {
  def apply() : Unit = {
    println("apply invoked")
  }

  def apply(name:String):String = {
    name
  }

  def apply(name:Int) : Int = {
    println("Int")
    name
  }

  /**
    * 从下面的案例中可以知道,若没有使用new关键字创建实例,它将使用相应的apply方法来创建实例
    * @param args
    */
  def main(args: Array[String]): Unit = {
   // //运行结果是:apply invoked
   //  val a1 = ApplyDemo()

    结果直接是tom
    //val a2 = ApplyDemo("tom")

    //结果是:Int
    val a3 = ApplyDemo(10)
    //打印的结果是:10
    println(a3)
  }
}

1.6. 应用程序对象

Scala程序都必须从一个对象的main方法开始,可以通过扩展App特质,不写main方法。

package cn.toto.scala.day2

/**
  * Created by toto on 2017/6/30.
  * //运行结果是:I love you Scala
  */
object AppObjectDemo extends App{

  //不用写main方法
  println("I love you Scala")
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涂作权的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值