2016-11-25 4 views
2

私は以下の質問があります。私たちのプロジェクトにはたくさんのコードがあり、Scalaでテストを実行します。そして、このようなフィールドを埋めるコードの多くは、そこにある:Scalaは、実際に呼び出し元が期待する戻り値の型から実際の型を推論できますか?

production.setProduct(new Product) 
production.getProduct.setUuid("b1253a77-0585-291f-57a4-53319e897866") 
production.setSubProduct(new SubProduct) 
production.getSubProduct.setUuid("89a877fa-ddb3-3009-bb24-735ba9f7281c") 

は最終的に、私は、これらすべてのフィールドは、実際にUUIDフィールドを持つ基本クラスのサブクラスであるため、このコードから疲れて育ったので、

production.setProduct(createUuid[Product]("b1253a77-0585-291f-57a4-53319e897866")) 
production.setSubProduct(createUuid[SubProduct]("89a877fa-ddb3-3009-bb24-735ba9f7281c")) 

:しばらく考えた後、私はこのような補助関数を書いた:今、私はこのような何かを書くことができますので、今

def createUuid[T <: GenericEntity](uuid: String)(implicit m : Manifest[T]) : T = { 
    val constructor = m.runtimeClass.getConstructors()(0) 
    val instance = constructor.newInstance().asInstanceOf[T] 
    instance.setUuid(uuid) 
    instance 
} 

を、私のコードは、2回短くなりましたそれは良いことだが、最後のビットは、この希望ので、私は何とか機能createUuidを実装することができれば、私は、疑問に思って:

// Is that really possible? 
production.setProduct(createUuid("b1253a77-0585-291f-57a4-53319e897866")) 
production.setSubProduct(createUuid("89a877fa-ddb3-3009-bb24-735ba9f7281c")) 

缶Scalaのコンパイラの推測を、そのsetProductだけではなく、一般的なエンティティが、実際の製品のようなものを期待します(またはそのサブクラス)?あるいはこれをさらに短く実装する方法はありませんか?

答えて

1

Scalaコンパイラは、タイプの外部をとして推論/伝播しません。ただしのような暗黙の型変換を作成することができます。

implicit def stringToSubProduct(uuid: String): SubProduct = { 
    val n = new SubProduct 
    n.setUuid(uuid) 
    n 
} 

してからちょうど

production.setSubProduct("89a877fa-ddb3-3009-bb24-735ba9f7281c") 

を呼び出し、それが入力および出力の該当するタイプを持っているので、コンパイラが自動的にstringToSubProductを使用します。


更新:は、私は同じように、コンパニオンオブジェクトにimplicit def Sを包むお勧めし、より良い組織化コードを持っている:

case class EntityUUID(uuid: String) { 
    uuid.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}") // possible uuid format check 
} 
case object EntityUUID { 

    implicit def toProduct(e: EntityUUID): Product = { 
    val p = new Product 
    p.setUuid(e.uuid) 
    p 
    } 

    implicit def toSubProduct(e: EntityUUID): SubProduct = { 
    val p = new SubProduct 
    p.setUuid(e.uuid) 
    p 
    } 
} 

、その後、あなたがしたい

production.setProduct(EntityUUID("b1253a77-0585-291f-57a4-53319e897866")) 

誰もがこれを読んでいると、変換の実装を見つけるための直感を得ることができます。

いくつかの一般的なアプローチ(30種類)についてのあなたのコメントに関して、私はそれは不可能ではないと言いますが、どうやってそれを行うのか分かりません。あなたが使用した反射はタイプシステムをバイパスします。 30件すべてが同じコードの場合は、オブジェクトデザインを再考する必要があります。今度は、あなたが提供したのと同じようなリフレクションを使用するいくつかのメソッドを呼び出すことによって、3implicit defを実装することができます。しかし、あなたはこの1つの場所(30)で将来変更することができます。

+0

私はGenericEntityのサブクラスである約30の型を持っていますが、このような暗黙のdefを書く必要がありますか?あるいは、私はそれを1回だけ行うことができますか? –

関連する問題