2016-11-25 46 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領域的基本類的子類,所以,想了一會兒後,我寫了這樣的輔助功能:

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 
} 

現在,我的代碼更短了兩次,因爲現在我可以寫這樣的事:

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

這是很好的,但我想知道,如果我能以某種方式實現功能createUuid所以最後一點想這樣:

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

燦Scala編譯器的猜測,即setProduct希望不只是一個普通的實體,但實際上類似產品(或它的子類)?或者Scala沒有辦法實現這個更短的?

回答

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個案例都是相同的代碼,也許你應該重新考慮你的對象設計。現在您仍然可以通過調用一些使用與您提供的反射相似的方法來實現30 implicit def。但是,您可以選擇在未來的一(30)個地點進行更改。

+0

我有大約30種類型,這是GenericEntity的子類,我必須爲它們所有人寫這樣的隱式def嗎?或者我可以只做一次? –

相關問題