Scala:哪些类不应该有伴侣对象?

时间:2017-08-22 16:17:21

标签: scala companion-object

以下模式似乎是惯用的scala:

class Foo() {}
object Foo { def apply() = new Foo() }
val x = Foo()

惯用法的动机是什么?在哪些情况下,我应提供工厂方法,强制客户使用val y = new Foo()?是否所有具有伴随对象的案例都提供工厂方法?

2 个答案:

答案 0 :(得分:0)

如果以下都不适用,则类不需要伴随对象:

  • 该类中的功能与实例无关(Java中称为“静态”)
  • 希望提供一种避免调用new的构造函数。这是通过SomeClass.apply(params)
  • 在Scala中完成的

如果不感兴趣,则不需要伴随对象。 伴侣对象是一种有用的结构 - 如果您有这些需求。如果没有,没有理由拥有它。我不知道断然不有任何伴侣对象的理由。如果你不需要,这是一个你不写的工具。

答案 1 :(得分:0)

Case class apply通常由编译器重写为new。如果你写一个自定义申请,即使是一个微不足道的申请,也不会这样做。

隐式值类可能存在类似的边缘情况。

$ scala
Welcome to Scala 2.12.3 (OpenJDK 64-Bit Server VM, Java 1.8.0_131).
Type in expressions for evaluation. Or try :help.

scala> case class K(i: Int)
defined class K

scala> K(42)
res0: K = K(42)

scala> :javap -c res0
Compiled from "<console>"
public class $line4.$read$$iw$$iw$ {
  public static $line4.$read$$iw$$iw$ MODULE$;

  public static {};
    Code:
       0: new           #2                  // class $line4/$read$$iw$$iw$
       3: invokespecial #28                 // Method "<init>":()V
       6: return

  public $line3.$read$$iw$$iw$K res0();
    Code:
       0: aload_0
       1: getfield      #31                 // Field res0:L$line3/$read$$iw$$iw$K;
       4: areturn

  public $line4.$read$$iw$$iw$();
    Code:
       0: aload_0
       1: invokespecial #33                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: putstatic     #35                 // Field MODULE$:L$line4/$read$$iw$$iw$;
       8: aload_0
       9: new           #14                 // class $line3/$read$$iw$$iw$K
      12: dup
      13: bipush        42
      15: invokespecial #38                 // Method $line3/$read$$iw$$iw$K."<init>":(I)V
      18: putfield      #31                 // Field res0:L$line3/$read$$iw$$iw$K;
      21: return
}

scala> case class K(i: Int) ; object K { def apply(j: Int) = new K(j) }
defined class K
defined object K

scala> K(42)
res1: K = K(42)

scala> :javap -c res1
Compiled from "<console>"
public class $line6.$read$$iw$$iw$ {
  public static $line6.$read$$iw$$iw$ MODULE$;

  public static {};
    Code:
       0: new           #2                  // class $line6/$read$$iw$$iw$
       3: invokespecial #31                 // Method "<init>":()V
       6: return

  public $line5.$read$$iw$$iw$K res1();
    Code:
       0: aload_0
       1: getfield      #34                 // Field res1:L$line5/$read$$iw$$iw$K;
       4: areturn

  public $line6.$read$$iw$$iw$();
    Code:
       0: aload_0
       1: invokespecial #36                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: putstatic     #38                 // Field MODULE$:L$line6/$read$$iw$$iw$;
       8: aload_0
       9: getstatic     #41                 // Field $line5/$read$$iw$$iw$K$.MODULE$:L$line5/$read$$iw$$iw$K$;
      12: bipush        42
      14: invokevirtual #45                 // Method $line5/$read$$iw$$iw$K$.apply:(I)L$line5/$read$$iw$$iw$K;
      17: putfield      #34                 // Field res1:L$line5/$read$$iw$$iw$K;
      20: return
}