我正在从一个非常硬编码的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;
}
因此,在Scala方面,我尝试使用案例对象来实现不同类型,这些案例对象都从基础Type
扩展。
sealed class Type(val name: String)
case object NewFoo extends Type("New Foo")
case object BarShared extends Type("Bar Shared")
问题是,由于我的应用程序是模块化的,我的MessageService
我无法访问Foo.findById
,Bar.findById
或Baz.findById
。我希望在参数列表中接收相应的字符串,但正如您所看到的,参数的数量因Type
而异。我可以使参数可选,但是任何调用该函数的人都需要根据类型知道哪些参数是必需的,我不喜欢这样。我想我可以为每种类型设置不同的功能名称,但我不愿意,如果有更好的方法。
答案 0 :(得分: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 :(得分: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)
答案 2 :(得分:0)
你仍然可以使用sealed
实现来获得一个简单的匹配语句,你只需要一个抽象类作为基础。
sealed abstract class MessageType {
val name: String
def findById[A](relatedId: Long): A
}
然后,您可以根据用例扩展案例对象或案例类:
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 = {...}
}
对于密封类,您的匹配语句不需要默认值,除非您将其定义为扩展名。