美文网首页python机器学习爬虫Scala学习
Scala类的主辅构造器,单例对象,伴生对象,工厂模式

Scala类的主辅构造器,单例对象,伴生对象,工厂模式

作者: xiaogp | 来源:发表于2020-09-16 11:42 被阅读0次

    摘要:scala构造器this关键字伴生对象单例对象工厂模式

    类的主构造器

    • 一个类只能有一个主构造器
    • 主构造器成员变量直接跟在class类名后面
    • 主构造器的入参需要用varval修饰,否则不能访问入参成员变量,相当于外部变量,val修饰的成员变量不能修改
    • 主构造器入参可以传入private,则成员变量在类外部不可访问,默认不写是public可以使用类名.变量访问
    • 主构造器入参可以有默认值,有默认值的参数写在最后,传参时可以部分传参,但是顺序要一致
    • 如果主构造器入参为空,类名的()可以不写
    class Student1(var name: String, var age: Int) {
      def getOne: String = "name" + ":" + name + " " + "age" + ":" + age
    }
    
    class Student2(var name: String = "gp", var age: Int = 13) {
      def getOne: String = "name" + ":" + name + " " + "age" + ":" + age
    }
    
    class Student2(private var name: String = "gp", private var age: Int = 13) {
      def getOne: String = "name" + ":" + name + " " + "age" + ":" + age
    }
    

    类的辅构造器

    • 一个类可以有多个辅构造器
    • 每一个辅助构造器都必须以一个先前已定义的其他辅助构造器或主构造器的调用开始
    • 使用def this(...) {...}定义辅构造器,花括号后面直接跟this(...)关键字调用已有辅构造器或者主构造器,通过传参方式确定到底调用的是哪个构造器,期望调用的构造器接受的参数要和this(...)括号中的一致
    • 辅构造器可以和主构造器配合一起构造类,此时既接受主构造器参数,也接受辅构造器参数
    • 纯辅构造器在开头定义成员变量初始值,null可以直接用_代替

    辅构造器的基本写法,调用this关键字

    class Student3 {
      var name: String = _
      var age: Int = _
    
      // this辅助构造器
      def this(name: String, age: Int) {
        // 辅助构造函数必须调用主构造函数或者通过this()之间相互调用
        this()
        this.name = name
        this.age = age
      }
    
      def getOne: String = "name" + ":" + name + " " + "age" + ":" + age
    }
    

    申明成员变量初始值为空,并且申明为private

    class Student4 {
      private var name: String = _
      private var age: Int = _
    
      def this(name: String, age: Int) {
        this() // 调用主构造器,主构造器无参
        this.name = name
        this.age = age
      }
    
      def getOne: String = "name" + ":" + name + " " + "age" + ":" + age
    }
    

    有多个辅构造器,每个辅构造器必须调用已有辅构造器或者主构造器

    class Student5 {
      private var name: String = _
      private var age: Int = _
    
      def this(name: String) {
        this()
        this.name = name
      }
    
      //  def this(name: String, age: Int) {
      //    this(name)  // 调用第一个辅构造器
      //    this.age = age
      //  }
    
      def this(name: String, age: Int) {
        this() // 调用主构造器
        this.name = name
        this.age = age
      }
    
      def getOne: String = "name" + ":" + name + " " + "age" + ":" + age
    }
    

    使用辅构造器配合主构造器一起设定入参,辅构造器支持Array传参,实际上将Array转化格式传给主构造器

    class Student6(var name: String, var age: Int) {
      def this(param: Array[Any]) {
        this(param(0).asInstanceOf[String], param(1).asInstanceOf[Int])
      }
    
      def getOne: String = "name" + ":" + name + " " + "age" + ":" + age
    }
    

    判断类相等

    需要重写equals方法,使用isInstanceOf判断对象类型,如果类型一致比较成员变量是否相等

    class Student8(var name: String, var age: Int) {
      override
      def equals(obj: Any): Boolean = {
        if (!obj.isInstanceOf[Student8]) {
          false
        } else {
          this.name == obj.asInstanceOf[Student8].name
          true
        }
      }
    }
    

    单例对象

    Scala中单例对象使用object关键字(类使用class关键字),单例对象不带参数,而类可以。单例对象是延迟创建的,当它第一次被使用时创建
    创建一个单例对象

    object ObjectTest {
      println("创建一个单例对象")
      private var num: Int = 1
    
      def getNum(): Unit = {
        num += 1
        println(num)
      }
    }
    

    单例可以在程序的任何其他地方被引用,在其他脚本import路径导入调用

    import ObjectTest.getNum
    
    object ObjectTest2 {
      def main(args: Array[String]): Unit = {
        getNum()
        getNum()
        getNum()
      }
    }
    

    输出2,3,4,可见只创建一个对象实例,公用的一个num

    创建一个单例对象
    2
    3
    4
    

    一个实际案例使用object构造MySQL工具类对象单例,对象内部实现方法传参构造单例MySQL连接池对象

    import org.apache.commons.dbcp.BasicDataSource
    import java.util.Properties
    
    object MysqlUtils {
      private var mysqlConns: BasicDataSource = null
      def getConnPool(prop: Properties) = {
        this.synchronized {
          if (null == mysqlConns) {
            mysqlConns = new BasicDataSource()
            mysqlConns.setDriverClassName(prop.getProperty("jdbc.driver"))
            mysqlConns.setUrl(prop.getProperty("jdbc.url"))
            mysqlConns.setUsername(prop.getProperty("jdbc.user"))
            mysqlConns.setPassword(prop.getProperty("jdbc.passwd"))
            mysqlConns.setMaxActive(4)
            mysqlConns.setMaxIdle(4)
            mysqlConns.setMinIdle(2)
            mysqlConns.setInitialSize(4)
            mysqlConns.setMaxWait(10000)
            mysqlConns.setTestWhileIdle(true)
            mysqlConns.setValidationQuery("select 1")
            mysqlConns.setValidationQueryTimeout(10000)
            mysqlConns.setTimeBetweenEvictionRunsMillis(10000)
          }
          mysqlConns
        }
      }
    }
    

    伴生对象

    当一个单例对象和某个类共享一个名称时,这个单例对象称为 伴生对象。 同理,这个类被称为是这个单例对象的伴生类。类和它的伴生对象必须定义在同一个源文件中。类和它的伴生对象可以互相访问其私有成员。
    一个例子在伴生类中调用伴生对象的私有变量,在其他脚本依旧需要new一个对象。

    class PairTest {
      private var name: String = _
      private var age: Int = _
    
      def this(name: String, age: Int) {
        this()
        this.name = name
        this.age = age
      }
    
      // 在class中访问object中的私有变量
      def getOne(): Unit = {println("name" + " " + name + " " + "age" + " " + age + " " + "degree" + " " + PairTest.degree + " " + "city" + " " + PairTest.city)}
    
    }
    
    object PairTest {
      private val degree: String = "本科"
      private val city: String = "苏州"
    
      def main(args: Array[String]): Unit = {
        val pairTest: PairTest = new PairTest("gp", 12)
        pairTest.getOne()
      }
    }
    
    name gp age 123 degree 本科 city 苏州
    

    工厂模式

    通常将伴生对象作为工厂使用,在伴生对象中使用工厂模式,创建单例对象,在其他脚本getInstance不需要new

    import java.util.Properties
    
    class PairTest {
      private var name: String = _
      private var age: Int = _
    
      private def this(name: String, age: Int) {
        this()
        this.name = name
        this.age = age
      }
    
      def getOne(): Unit = {
        println("name" + " " + name + " " + "age" + " " + age)
      }
    
    }
    
    object PairTest {
      private var instance: PairTest = _
    
      def getInstance(prop: Properties): PairTest = {
        if (instance == null) {
          this.synchronized {
            if (instance == null) {
              instance = new PairTest(prop.getProperty("name"), Integer.parseInt(prop.getProperty("age")))
            }
          }
        }
        instance
      }
    
      def main(args: Array[String]): Unit = {
        val prop: Properties = new Properties() {{
          setProperty("name", "gp")
          setProperty("age", "12")
        }}
        PairTest.getInstance(prop).getOne()  // name gp age 12
      }
    }
    

    相关文章

      网友评论

        本文标题:Scala类的主辅构造器,单例对象,伴生对象,工厂模式

        本文链接:https://www.haomeiwen.com/subject/twzfyktx.html