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进行定义。这叫做静态转化,这个一般出现在即使你没有定义伴生类的时候。