2014-05-15 35 views
2

我正在從一個非常硬編碼的Java實現轉移到一個非常模塊化的Scala實現,並且我已經停止了翻譯我的應用程序的一部分。基於案例對象的參數

我正在看的函數從格式字符串中產生一條消息。它在數據庫中查找相關信息並使用它來格式化字符串。

public static String getHumanizedMessage(Type type, User user, Long relatedId){ 
    switch(type.getTypeName()){ 
    case NEW_FOO:{ 
     Foo foo = Foo.findById(relatedId); 
     return String.format(type.getMessage(), user.name, foo.name); 
    } 
    case BAR_SHARED:{ 
     Bar bar = Bar.findById(relatedId); 
     Baz baz = Baz.findById(relatedId); 
     return String.format(type.getMessage(), user.name, bar.name, baz.name); 
    } 
    default: 
     break; 
    } 
    return null; 
} 

因此,對事物的斯卡拉的一面,我一直試圖實現使用情況的對象的不同類型,所有從基地Type延伸。

sealed class Type(val name: String) 

case object NewFoo extends Type("New Foo") 
case object BarShared extends Type("Bar Shared") 

問題是,我的申請是模塊化的,在我MessageService我用不上Foo.findByIdBar.findByIdBaz.findById。我希望它在參數列表中收到適當的字符串,但正如您所看到的,參數的數量根據Type而有所不同。我可以將參數設置爲可選,但是任何調用函數的人都需要根據類型知道哪些參數是必需的,我不喜歡這樣。我想我可以爲每種類型都有不同的函數名稱,但我寧願不要,如果有更好的方法。

+2

恐怕我不能真正按照你的最後一段。你能否改寫/澄清你想要做什麼?這是什麼'MessageService'?你想在哪裏收到適當的字符串? – DCKing

+0

我打算把項目分解成模塊,這些模塊有提供功能的服務。這一切都發生在我的'MessageService'中,它無法訪問'UserService'或'BarService'以調用像'findById'這樣的數據庫方法。所以我的'getHumanizedMessage'不能只把'relatedId'作爲參數並找到它需要的對象。我想採取'字符串'參數。但是我需要的字符串數量並不總是相同的。 – mgeiger

回答

1

我認爲你可能需要對這種類型的格式化Type的知識進行編碼。如果您的目標是保持MessageService對於可能進入的任何數據不可知,您可以例如要求每個類型本身格式,如:

trait MessageType { 
    val name: String 
    def format(relatedId: Long): String 
} 

case class FooMessageType(foo: Foo) extends MessageType { 
    val name = "Foo" 
    def format(relatedIid: Long) = { 
    val foo = Foo.findById(relatedId) 
    "This is ${foo.name}" 
    } 
} 

那麼您會MessageService只瞭解MessageType接口,和實現它們的將在不同的模塊來提供。請注意,您可能需要允許每個模塊在啓動時針對MessageService註冊其MessageType。

1

對我來說這似乎很奇怪,這個getHumanizedMessage()是一個單一的方法開始。由於你的switch語句,你在一個函數中做了兩件完全不同的事情。你爲什麼不把它們分開?

你可以寫:

def getHumanizedMessage(foo: Foo, user: User) = String.format(NewFoo.getMessage(), user.name, foo.name) 
def getHumanizedMessage(bar: Bar, baz: Baz, user: User) = String.format(BarShared.getMessage(), bar.name, baz.name, user.name) 
0

,您仍然可以使用sealed實施一個簡單的匹配語句,你只需要有一個抽象類爲基礎。

sealed abstract class MessageType { 
    val name: String 
    def findById[A](relatedId: Long): A 
} 

然後,您可以擴展的情況下物體或根據您的使用情況case類:

case object NewFoo extends MessageType { 
    val name: String = "NewFoo" 
    def findById(relatedId: Long): NewFoo = {...} 
} 

,或者如果你想提供的參數:

case class BarShared(defaultName: String) extends MessageType { 
    val name: String = defaultName 
    def findById(relatedId: Long) BarShared = {...} 
} 

隨着密封類的比賽語句不需要默認值,除非將其定義爲擴展名。