zoukankan      html  css  js  c++  java
  • scala之旅-核心语言特性【单例对象】(十五)

    object 是一个类有且唯一的实例。当对象被引用时,它是懒模式创建的,就像 lazy val一样。

    作为一个顶级的值,对象是单例的。

    作为一个封闭类的成员或者局部值时,它的行为更像是一个lazy val。

    定义一个单例的对象

    对象是一个值。定义一个对象看起来像定义一个类,但是是用关键字 object:

    object Box

    下面是一个关于对象的例子,这个对象有一个方法:

    package logging
    
    object Logger {
      def info(message: String): Unit = println(s"INFO: $message")
    }

    这个info 方法可以被程序的任何地方导入。像这样创建一个实用方法是对单例对象的普遍使用方式。

    让我们看看如何在其他包中使用info方法:

    import logging.Logger.info
    
    class Project(name: String, daysToComplete: Int)
    
    class Test {
      val project1 = new Project("TPS Reports", 1)
      val project2 = new Project("Website redesign", 5)
      info("Created projects")  // Prints "INFO: Created projects"
    }

    通过import语句 import logging.Logger.info,info方法就可以被访问。

    import 需要一个全路径,对象也是全路径导入。

    注意:如果一个对象不是顶级的,但是是内嵌在其他类或者对象里面的,那么这个对象的需要用 全路径+依赖的方式,与类其他成员访问方式一样。这意味着给定两种饮料类,类 Milk和类 OrangeJuice, 一个类成员 object NutritionInfo 依赖于封闭的实例,无论是 milk 还是 orangeJuice,milk.NutritionInfo 和 oj.NutritionInfo 都是不一样的。

    对象的比较

    与类同名的对象称之为伴生对象。相反,这个类称之为伴生类。伴生类或对象可以访问与其伴生的内部私有成员。将伴生对象用于伴生类实例中没有指明的方法和值。

    import scala.math._
    
    case class Circle(radius: Double) {
      import Circle._
      def area: Double = calculateArea(radius)
    }
    
    object Circle {
      private def calculateArea(radius: Double): Double = Pi * pow(radius, 2.0)
    }
    
    val circle1 = Circle(5.0)
    
    circle1.area

    这里的类 Circle有一个在实例指定的area成员,单例对象Circle有一个 calculateArea方法,这个方法每个实例都可以访问。

    伴生对象当然也可以包含工厂方法:

    class Email(val username: String, val domainName: String)
    
    object Email {
      def fromString(emailString: String): Option[Email] = {
        emailString.split('@') match {
          case Array(a, b) => Some(new Email(a, b))
          case _ => None
        }
      }
    }
    
    val scalaCenterEmail = Email.fromString("scala.center@epfl.ch")
    scalaCenterEmail match {
      case Some(email) => println(
        s"""Registered an email
           |Username: ${email.username}
           |Domain name: ${email.domainName}
         """.stripMargin)
      case None => println("Error: could not parse email")
    }

    这个对象 Email 包含一个工厂 fromString 用来从一个字符串中创建一个Email。 以防解析错误,我们用一个 Option[Email] 返回。

    注:如果一个类或对象有伴生,那么它们必须在一个文件里面定义。要在REPL中定义伴生,请在同一行上定义它们或进入:paste模式 【注:这句话我没看懂~】

    Java开发者注意

    java的static 成员被建模在scala的伴生对象的普通成员。

    当从java代码中使用伴生对象时,伴生对象成员将会在伴生类里面用一个static进行定义。这叫做静态转化,这个一般出现在即使你没有定义伴生类的时候。

  • 相关阅读:
    题解 CF934A 【A Compatible Pair】 ——贪心
    洛谷 P3381 【【模板】最小费用最大流】
    洛谷 P3376 【【模板】网络最大流】
    洛谷 P1027 【Car的旅行路线】
    TYVJ P1039 【忠诚2】
    洛谷 P1273 【有线电视网】
    斯特林数相关
    从 简单容斥 到 min-max 容斥 与 二项式反演
    POI2011 Lightning Conductor
    LOJ6089 小 Y 的背包计数问题
  • 原文地址:https://www.cnblogs.com/zhouwenyang/p/13891622.html
Copyright © 2011-2022 走看看