【Scala】Scala之Object(二)

简介: 前面学习了Scala的Methods,接着学习Scala中的Object

2.7 将常用代码放在包对象中

  1. 问题描述

  你想要使方法、字段和其他代码处于包级别,而不需要class或者object

  2. 解决方案

  将代码放置在包对象下面,如将你的代码放置在package.scala文件中,例如,如果你想要代码被com.hust.grid.leesf.model包下所有类可用,那么创建一个位于com/hust/grid/leesf/model目录下的package.scala文件,在package.scala中,在包声明中移除model,并且以其作为名字来创建包,大致如下 

package com.hust.grid.leesf
package object model {

 其他代码放置在model中,如下所示

package com.hust.grid.leesf
package object model {
    // field
    val MAGIC_NUM = 42
    // method
    def echo(a: Any) { println(a) }
    // enumeration
    object Margin extends Enumeration {
        type Margin = Value
        val TOP, BOTTOM, LEFT, RIGHT = Value
    }
    // type definition
    type MutableMap[K, V] = scala.collection.mutable.Map[K, V]
    val MutableMap = scala.collection.mutable.Map
}

 此时,在com.hust.grid.leesf.model包下面类、对象、接口等可以随意访问上述定义的字段、方法等

package com.hust.grid.leesf.model
object MainDriver extends App {
    // access our method, constant, and enumeration
    echo("Hello, world")
    echo(MAGIC_NUM)
    echo(Margin.LEFT)
    // use our MutableMap type (scala.collection.mutable.Map)
    val mm = MutableMap("name" -> "Al")
    mm += ("password" -> "123")
    for ((k,v) <- mm) printf("key: %s, value: %s\n", k, v)
}

3. 讨论

  最疑惑的是将package对象放在哪里,其包名和对象名

  如果你想要让你的代码在com.hust.grid.leesf.model包中可见,那么将package.scala放在com/hust/grid/leesf/model目录下,而在package.scala中,其包名应该如下 

package com.hust.grid.leesf

然后使用model作为对象名

package object model {

 最后大致如下 

package com.hust.grid.leesf
package object model {

包中可以存放枚举类型、常量和隐式转换

  2.8 不使用new关键字来创建对象实例

  1. 问题描述

  当不使用new关键字来创建对象时,Scala代码会显得相对简洁,如下所示  

val a = Array(Person("John"), Person("Paul"))

2. 解决方案

  有两种方式

    · 为类创建伴生对象,然后定义apply方法,其签名与构造方法签名相同

    · 将类定义为case类

  为Person对象定义了伴生对象,然后定义apply方法并接受参数

class Person {
    var name: String = _
}
object Person {
    def apply(name: String): Person = {
        var p = new Person
        p.name = name
        p
    }
}    

 现在你可以不使用new关键字来创建Person对象了  

val dawn = Person("Dawn")
val a = Array(Person("Dan"), Person("Elijah"))

Scala编译器会对伴生对象中的apply进行特殊处理,让你不使用new关键字即可创建对象

  将类定义为case类,并且接受相应参数  

case class Person (var name: String)

 现在可以采用如下方法创建对象

val p = Person("Fred Flinstone")

Scala会为case类的伴生对象创建apply方法

  3. 讨论

  编译器会对伴生对象的apply做特殊处理,这是Scala的语法糖 

val p = Person("Fred Flinstone")

 上述代码会被转化为如下代码 

val p = Person.apply("Fred Flinstone")

 apply方法是工厂方法,Scala的此语法糖让你不用new关键字即可创建对象

  可以在伴生对象中创建多个apply方法,这样相当于多个构造函数

class Person {
    var name = ""
    var age = 0
}
object Person {
    // a one-arg constructor
    def apply(name: String): Person = {
        var p = new Person
        p.name = name
        p
    }
    // a two-arg constructor
    def apply(name: String, age: Int): Person = {
        var p = new Person
        p.name = name
        p.age = age
        p
    }
}

可以使用如下方法创建对象 

val fred = Person("Fred")
val john = Person("John", 42)

为了给case类创建多个构造函数,需要知道case类背后的逻辑

  当使用scala编译器编译case类时,你会发生其生成了两个文件,Person$.class和Person.class文件,当使用javap反编译Person$.class文件时,其输出如下

  9.png

  其包含了一个返回Person对象的apply方法 

public Person apply(java.lang.String);

 String对应的是case类中的name 

case class Person (var name: String)

 使用javap命令可以看到在Person.class中为name生成的getter和setter函数

  10.png

  在如下代码中,存在case类和apply方法 

// want accessor and mutator methods for the name and age fields
case class Person (var name: String, var age: Int)
// define two auxiliary constructors
object Person {
    def apply() = new Person("<no name>", 0)
    def apply(name: String) = new Person(name, 0)
}

 由于name和age都是var的,所以会生成getter和setter,在object中定义了两个apply函数,因此可以使用如下三种方式来生成Person对象 

object Test extends App {
    val a = Person()
    val b = Person("Al")
    val c = Person("William Shatner", 82)
    println(a)
    println(b)
    println(c)
    // test the mutator methods
    a.name = "Leonard Nimoy"
    a.age = 82
    println(a)
}

 其结果如下  

Person(<no name>,0)
Person(Al,0)
Person(William Shatner,82)
Person(Leonard Nimoy,82)

 2.9 使用apply来实现工厂方法

  1. 问题描述

  为了让子类声明应该创建哪种类型的对象,并且只在一处能够创建对象,你想要实现工厂方法

  2. 解决方案

  可以使用伴生对象的apply方法来实现工厂方法,你可将工厂实现算法放置在apply方法中

  假设你想要创建一个Animal工厂,并且返回Cat和Dog,在Animal类的伴生对象中实现apply方法,你就可以使用如下方式创建不同对象 

val cat = Animal("cat") // creates a Cat
val dog = Animal("dog") // creates a Dog

 首先需要创建一个Animal的trait  

trait Animal {
    def speak
}

 然后在相同文件中创建伴生对象,创建实现Animal的类,一个合适的apply方法 

object Animal {
    private class Dog extends Animal {
        override def speak { println("woof") }
    }
    private class Cat extends Animal {
        override def speak { println("meow") }
    }
    // the factory method
    def apply(s: String): Animal = {
        if (s == "dog") new Dog
        else new Cat
    }
}

 然后就可以使用如下语句创建不同对象

val cat = Animal("cat") // creates a Cat
val dog = Animal("dog") // creates a Dog

 3. 讨论

  如果不使用apply方法来实现工厂方法,也可以使用如下的getAnimal方法来实现上述功能  

// an alternative factory method (use one or the other)
def getAnimal(s: String): Animal = {
    if (s == "dog") return new Dog
    else return new Cat
}

然后可以使用如下方法创建不同对象 

val cat = Animal.getAnimal("cat") // returns a Cat
val dog = Animal.getAnimal("dog") // returns a Dog

 以上两种方法都是可行的


三、总结


  本篇学习了Scala中的object及其相应的用法,其在Scala的实际编程中应用也是非常广泛,也谢谢各位园友观看~

目录
相关文章
|
7月前
|
分布式计算 Java Scala
Scala:面向对象、Object、抽象类、内部类、特质Trait(二)
Scala:面向对象、Object、抽象类、内部类、特质Trait(二)
99 0
|
XML IDE Java
【Scala】Scala之Object(一)
前面学习了Scala的Methods,接着学习Scala中的Object
216 0
【Scala】Scala之Object(一)
|
Scala Java
[Scala]Scala学习笔记五 Object
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SunnyYoona/article/details/76423770 1.
1148 0
|
2月前
|
分布式计算 大数据 Java
大数据-87 Spark 集群 案例学习 Spark Scala 案例 手写计算圆周率、计算共同好友
大数据-87 Spark 集群 案例学习 Spark Scala 案例 手写计算圆周率、计算共同好友
69 5
|
2月前
|
分布式计算 关系型数据库 MySQL
大数据-88 Spark 集群 案例学习 Spark Scala 案例 SuperWordCount 计算结果数据写入MySQL
大数据-88 Spark 集群 案例学习 Spark Scala 案例 SuperWordCount 计算结果数据写入MySQL
55 3
|
2月前
|
消息中间件 分布式计算 NoSQL
大数据-104 Spark Streaming Kafka Offset Scala实现Redis管理Offset并更新
大数据-104 Spark Streaming Kafka Offset Scala实现Redis管理Offset并更新
45 0
|
2月前
|
消息中间件 存储 分布式计算
大数据-103 Spark Streaming Kafka Offset管理详解 Scala自定义Offset
大数据-103 Spark Streaming Kafka Offset管理详解 Scala自定义Offset
101 0
|
2月前
|
分布式计算 大数据 Java
大数据-86 Spark 集群 WordCount 用 Scala & Java 调用Spark 编译并打包上传运行 梦开始的地方
大数据-86 Spark 集群 WordCount 用 Scala & Java 调用Spark 编译并打包上传运行 梦开始的地方
40 1
大数据-86 Spark 集群 WordCount 用 Scala & Java 调用Spark 编译并打包上传运行 梦开始的地方
|
2月前
|
SQL 分布式计算 Java
大数据-96 Spark 集群 SparkSQL Scala编写SQL操作SparkSQL的数据源:JSON、CSV、JDBC、Hive
大数据-96 Spark 集群 SparkSQL Scala编写SQL操作SparkSQL的数据源:JSON、CSV、JDBC、Hive
59 0