9

私はそのように定義されたケースクラスを持っています:

case class StreetSecondary(designator: String, value: Option[String])

次に、明示的なコンパニオン オブジェクト を定義します。

object StreetSecondary {
  //empty for now
}

明示的なコンパニオン オブジェクト StreetSecondary を定義すると、コンパイラによって生成された "暗黙的なコンパニオン オブジェクト" が失われます。つまり、コンパイラによって生成されたバージョンにアクセスできなくなります。たとえば、tupledメソッドは、この暗黙的なコンパニオン オブジェクトを介してケース クラス StreetSecondary で使用できます。ただし、明示的なコンパニオン オブジェクトを定義すると、tupledメソッドは「失われます」。

では、上記の StreetSecondary の明示的なコンパニオン オブジェクトを定義/追加/変更して、コンパイラが提供する暗黙的なコンパニオン オブジェクトを置き換えることで失われたすべての機能を取り戻すにはどうすればよいでしょうか? tupledそして、メソッドが復元されるだけではありません。すべての機能 (extractor/ を含むなどunapply) を復元したい。

あなたが提供できる指示/ガイダンスに感謝します。


更新 1

いくつかのことを発見するのに十分な検索を行いました:

A) 明示的なコンパニオン オブジェクトは、そのケース クラスの前に定義する必要があります (少なくとも Eclipse Scala-IDE WorkSheet ではそうであり、コードは IntelliJ IDE の WorkSheet では、どちらが先であっても機能しません)。

B) 強制的に動作させるための技術的なトリックがありtupledます (drstevens に感謝します): これで特(StreetSecondary.apply _).tupled​​定のメソッドの問題は解決tupledされますが、暗黙のコンパニオン オブジェクトで scala コンパイラが提供しているものを正確または完全に説明することはできません。

C) 最後に、明示的なコンパニオン オブジェクトを定義して、プライマリ コンストラクタのパラメータのシグネチャに一致し、ケース クラスのインスタンスを返す関数を拡張できます。次のようになります。

object StreetSecondary extends ((String, Option[String]) => StreetSecondary) {
  //empty for now
}

繰り返しになりますが、暗黙のコンパニオン オブジェクトで scala コンパイラが提供しているものを正確に、または完全に説明する自信はまだありません。

4

3 に答える 3

5

(Scala 2.11 以降) ケース クラスの明示的なコンパニオン オブジェクトを定義する場合、失われた暗黙的なコンパニオン オブジェクトでコンパイラが提供する機能を完全に置き換えるために、明示的なコンパニオン オブジェクトの基本テンプレートには 2 つの要件があります。

要件:
1. ケース クラスの型を返すタプル (ケース クラス コンストラクター パラメーターの型と順序が正確に一致する) で構成される関数定義を拡張する
必要があります。 2. toString 関数をオーバーライドして、オブジェクト クラス名 (同一の関連するケースクラスのクラスに)

「空の」明示的なコンパニオン オブジェクトの元のサンプル コードは次のとおりです。

object StreetSecondary {
  //empty for now
}

上記の要件を実装した後のコード例を次に示します。

object StreetSecondary extends ((String, Option[String]) => StreetSecondary) {
    //replace the toString implementation coming from the inherited class (FunctionN)
    override def toString =
      getClass.getName.split("""\$""").reverse.dropWhile(x => {val char = x.take(1).head; !((char == '_') || char.isLetter)}).head
}

上記の要件 1 を満たすにextends ((String, Option[String]) => StreetSecondary)は、オブジェクト名の直後、最初の中かっこの前に挿入します。

上記の要件 2 を満たすためoverride def toString = getClass.getName.split("""\$""").reverse.dropWhile(x => {val char = x.take(1).head; !((char == '_') || char.isLetter)}).headに、オブジェクトの本体に挿入されます (明示的な実装には疑問が残ります)。

失われた機能を復元するために必要なのは上記の 2 つの手順だけであると確信できるように、javap の出力を投稿してくれた @drstevens に深く感謝します。

于 2014-08-20T20:45:32.320 に答える
3

スカラ 2.11.0

tupledコンパニオンで追加の関数を提供していない場合、scalac が関数を事前定義しているようです

case class BB(a: Int, b: Int)
object BB { }

case class AA(a: Int, b: Int)

object CC { }
case class CC(a: Int, b: Int)

結果は次のようになります

public class AA implements scala.Product,scala.Serializable {
  public static scala.Option<scala.Tuple2<java.lang.Object, java.lang.Object>> unapply(AA);
  public static AA apply(int, int);
  public static scala.Function1<scala.Tuple2<java.lang.Object, java.lang.Object>, AA> tupled();
  public static scala.Function1<java.lang.Object, scala.Function1<java.lang.Object, AA>> curried();
  public int a();
  public int b();
  public AA copy(int, int);
  public int copy$default$1();
  public int copy$default$2();
  public java.lang.String productPrefix();
  public int productArity();
  public java.lang.Object productElement(int);
  public scala.collection.Iterator<java.lang.Object> productIterator();
  public boolean canEqual(java.lang.Object);
  public int hashCode();
  public java.lang.String toString();
  public boolean equals(java.lang.Object);
  public AA(int, int);
}

public final class AA$ extends scala.runtime.AbstractFunction2<java.lang.Object, java.lang.Object, AA> implements scala.Serializable {
  public static final AA$ MODULE$;
  public static {};
  public final java.lang.String toString();
  public AA apply(int, int);
  public scala.Option<scala.Tuple2<java.lang.Object, java.lang.Object>> unapply(AA);
  public java.lang.Object apply(java.lang.Object, java.lang.Object);
}

public class BB implements scala.Product,scala.Serializable {
  public static scala.Option<scala.Tuple2<java.lang.Object, java.lang.Object>> unapply(BB);
  public static BB apply(int, int);
  public int a();
  public int b();
  public BB copy(int, int);
  public int copy$default$1();
  public int copy$default$2();
  public java.lang.String productPrefix();
  public int productArity();
  public java.lang.Object productElement(int);
  public scala.collection.Iterator<java.lang.Object> productIterator();
  public boolean canEqual(java.lang.Object);
  public int hashCode();
  public java.lang.String toString();
  public boolean equals(java.lang.Object);
  public BB(int, int);
}

public final class BB$ implements scala.Serializable {
  public static final BB$ MODULE$;
  public static {};
  public BB apply(int, int);
  public scala.Option<scala.Tuple2<java.lang.Object, java.lang.Object>> unapply(BB);
}

public class CC implements scala.Product,scala.Serializable {
  public static scala.Option<scala.Tuple2<java.lang.Object, java.lang.Object>> unapply(CC);
  public static CC apply(int, int);
  public int a();
  public int b();
  public CC copy(int, int);
  public int copy$default$1();
  public int copy$default$2();
  public java.lang.String productPrefix();
  public int productArity();
  public java.lang.Object productElement(int);
  public scala.collection.Iterator<java.lang.Object> productIterator();
  public boolean canEqual(java.lang.Object);
  public int hashCode();
  public java.lang.String toString();
  public boolean equals(java.lang.Object);
  public CC(int, int);
}

public final class CC$ implements scala.Serializable {
  public static final CC$ MODULE$;
  public static {};
  public CC apply(int, int);
  public scala.Option<scala.Tuple2<java.lang.Object, java.lang.Object>> unapply(CC);
}
于 2014-08-19T22:00:10.147 に答える
1

なぜあなたはそれらを失っていると思いますか?

case class Person(name: String, age: Int)
object Person {
  def apply(): Person = new Person("Bob", 33)
}

val alice = Person("Alice", 20)
val bob   = Person()

Person.unapply(alice)    //Option[(String, Int)] = Some((Alice,20))
Person.unapply(Person()) //Option[(String, Int)] = Some((Bob,33))

抽出器はまだあるようです。

あなたの場合、あなたはまだそれをすべて手に入れました:

scala> StreetSecondary.unapply _
res10: StreetSecondary => Option[(String, Option[String])] = <function1>
于 2014-08-19T21:05:27.370 に答える