In the work that I do on a day to day in Java, I use builders quite a lot for fluent interfaces, e.g.: new PizzaBuilder(Size.Large).onTopOf(Base.Cheesy).with(Ingredient.Ham).build();
With a quick-and-dirty Java approach, each method call mutates the builder instance and returns this. Immutably, it involves more typing, cloning the builder first before modifying it. The build method eventually does the heavy lifting over the builder state.
What's a nice way of achieving the same in Scala?
If I wanted to ensure that onTopOf(base:Base) was called only once, and then subsequently only with(ingredient:Ingredient) and build():Pizza could be called, a-la a directed builder, how would I go about approaching this?
Another alternative to the Builder pattern in Scala 2.8 is to use immutable case classes with default arguments and named parameters. Its a little different but the effect is smart defaults, all values specified and things only specified once with syntax checking...
The following uses Strings for the values for brevity/speed...
scala> case class Pizza(ingredients: Traversable[String], base: String = "Normal", topping: String = "Mozzarella")
defined class Pizza
scala> val p1 = Pizza(Seq("Ham", "Mushroom"))
p1: Pizza = Pizza(List(Ham, Mushroom),Normal,Mozzarella)
scala> val p2 = Pizza(Seq("Mushroom"), topping = "Edam")
p2: Pizza = Pizza(List(Mushroom),Normal,Edam)
scala> val p3 = Pizza(Seq("Ham", "Pineapple"), topping = "Edam", base = "Small")
p3: Pizza = Pizza(List(Ham, Pineapple),Small,Edam)
You can then also use existing immutable instances as kinda builders too...
scala> val lp2 = p3.copy(base = "Large")
lp2: Pizza = Pizza(List(Ham, Pineapple),Large,Edam)
You have three main alternatives here.
Use the same pattern as in Java, classes and all.
Use named and default arguments and a copy method. Case classes already provide this for you, but here's an example that is not a case class, just so you can understand it better.
object Size {
sealed abstract class Type
object Large extends Type
}
object Base {
sealed abstract class Type
object Cheesy extends Type
}
object Ingredient {
sealed abstract class Type
object Ham extends Type
}
class Pizza(size: Size.Type,
base: Base.Type,
ingredients: List[Ingredient.Type])
class PizzaBuilder(size: Size.Type,
base: Base.Type = null,
ingredients: List[Ingredient.Type] = Nil) {
// A generic copy method
def copy(size: Size.Type = this.size,
base: Base.Type = this.base,
ingredients: List[Ingredient.Type] = this.ingredients) =
new PizzaBuilder(size, base, ingredients)
// An onTopOf method based on copy
def onTopOf(base: Base.Type) = copy(base = base)
// A with method based on copy, with `` because with is a keyword in Scala
def `with`(ingredient: Ingredient.Type) = copy(ingredients = ingredient :: ingredients)
// A build method to create the Pizza
def build() = {
if (size == null || base == null || ingredients == Nil) error("Missing stuff")
else new Pizza(size, base, ingredients)
}
}
// Possible ways of using it:
new PizzaBuilder(Size.Large).onTopOf(Base.Cheesy).`with`(Ingredient.Ham).build();
// or
new PizzaBuilder(Size.Large).copy(base = Base.Cheesy).copy(ingredients = List(Ingredient.Ham)).build()
// or
new PizzaBuilder(size = Size.Large,
base = Base.Cheesy,
ingredients = Ingredient.Ham :: Nil).build()
// or even forgo the Builder altogether and just
// use named and default parameters on Pizza itself
Use a type safe builder pattern. The best introduction I know of is this blog, which also contains references to many other articles on the subject.
Basically, a type safe builder pattern guarantees at compile time that all required components are provided. One can even guarantee mutual exclusion of options or arity. The cost is the complexity of the builder code, but...
Case classes solve the problem as shown in previous answers, but the resulting api is difficult to use from java when You have scala collections in your objects. To provide a fluent api to java users try this:
case class SEEConfiguration(parameters : Set[Parameter],
plugins : Set[PlugIn])
case class Parameter(name: String, value:String)
case class PlugIn(id: String)
trait SEEConfigurationGrammar {
def withParameter(name: String, value:String) : SEEConfigurationGrammar
def withParameter(toAdd : Parameter) : SEEConfigurationGrammar
def withPlugin(toAdd : PlugIn) : SEEConfigurationGrammar
def build : SEEConfiguration
}
object SEEConfigurationBuilder {
def empty : SEEConfigurationGrammar = SEEConfigurationBuilder(Set.empty,Set.empty)
}
case class SEEConfigurationBuilder(
parameters : Set[Parameter],
plugins : Set[PlugIn]
) extends SEEConfigurationGrammar {
val config : SEEConfiguration = SEEConfiguration(parameters,plugins)
def withParameter(name: String, value:String) = withParameter(Parameter(name,value))
def withParameter(toAdd : Parameter) = new SEEConfigurationBuilder(parameters + toAdd, plugins)
def withPlugin(toAdd : PlugIn) = new SEEConfigurationBuilder(parameters , plugins + toAdd)
def build = config
}
Then in java code the api is really easy to use
SEEConfigurationGrammar builder = SEEConfigurationBuilder.empty();
SEEConfiguration configuration = builder
.withParameter(new Parameter("name","value"))
.withParameter("directGivenName","Value")
.withPlugin(new PlugIn("pluginid"))
.build();
It's the same exact pattern. Scala allows for mutation and side effects. That said, if you'd like to be more of a purest, have each method return a new instance of the object that you're constructing with the element(s) changed. You could even put the functions within the Object of a class so that there's a higher level of separation within your code.
class Pizza(size:SizeType, layers:List[Layers], toppings:List[Toppings]){
def Pizza(size:SizeType) = this(size, List[Layers](), List[Toppings]())
object Pizza{
def onTopOf( layer:Layer ) = new Pizza(size, layers :+ layer, toppings)
def withTopping( topping:Topping ) = new Pizza(size, layers, toppings :+ topping)
}
so that your code might look like
val myPizza = new Pizza(Large) onTopOf(MarinaraSauce) onTopOf(Cheese) withTopping(Ham) withTopping(Pineapple)
(Note: I've probably screwed up some syntax here.)
using Scala partial applies are feasible if you are building a smallish object that you don't need to pass over method signatures. If any of those assumptions don't apply, I recommend using a mutable builder to build an immutable object. With this being scala you could implement the builder pattern with a case class for the object to build with a companion as the builder.
Given that the end result is a constructed immutable object I don't see that it defeats any of the Scala principles.
Related
class Person(name: String, age: Int, numThings: Option[Int] = Some(15))
I can use Scala reflection to obtain defaults on a case class like this:
val companionType: Type = classSymbol.companion.typeSignature
val companionObject = currentMirror.reflectModule(classSymbol.companion.asModule).instance
val companionMirror = currentMirror.reflect(companionObject)
val defaultValueAccessorMirror =
if (member.typeSignature.typeSymbol.isClass) {
val defaultValueAccessor = companionType.member(TermName("apply$default$" + (index + 1)))
if (defaultValueAccessor.isMethod) {
Some(companionMirror.reflectMethod(defaultValueAccessor.asMethod))
} else {
None
}
} else {
None
}
This obtains the method in the generated companion object that, when called, coughs up the default value. Sadly, a non-case class doesn't appear to have this facility.
How can I obtain the default value for Person.numThings in the example above using either Scala or Java reflection?
I think that it should be much easier to retrieve these default values through Java reflection, instead of this over-complicated Scala's reflect...
When compiled into a .class file, default parameter values are translated into static methods with specific suffixes in names. These values can be retrieved by invoking the respective method on the class reference.
So, for example, we have both a case and a non-case classes:
class Person(name: String, age: Int, numThings: Option[Int] = Some(15))
case class Item(id: Long, other: String = "unknown")
First we need to determine the ordinal indices of the params to retrieve defaults for. I do not know your use case, so let's suppose you know or calculated them. They will be 3 for Person and 2 for Item. Yes, they are not 0-based.
And this very short method retrieves the values:
private def extractDefaultConstructorParamValue(clazz: Class[_],
iParam: Int): Any = {
val methodName = "$lessinit$greater$default$" + iParam
clazz.getMethod(methodName).invoke(clazz)
}
Calling them with
val defParamNonCase = extractDefaultConstructorParamValue(classOf[Person], 3)
val defParamCase = extractDefaultConstructorParamValue(classOf[Item], 2)
println(defParamNonCase)
println(defParamCase)
outputs
Some(15)
unknown
I need using a tester for Scala Spark filter, with tester implementing java's Predicate interface and receiving specific class name by arguments.
I'm doing something like this
val tester = Class.forName(qualifiedName).newInstance().asInstanceOf[Predicate[T]]
var filtered = rdd.filter(elem => tester.test(elem))
The problem is that at runtime i have a Spark "TaskNotSerializable Exception" because my specific Predicate class is not Serializable.
If I do
val tester = Class.forName(qualifiedName).newInstance()
.asInstanceOf[Predicate[T] with Serializable]
var filtered = rdd.filter(elem => tester.test(elem))
I get the same error.
If I create tester into rdd.filter call it works:
var filtered = rdd.filter { elem =>
val tester = Class.forName(qualifiedName).newInstance()
.asInstanceOf[Predicate[T] with Serializable]
tester.test(elem)
}
But I would create a single object (maybe to broadcast) for testing. How can I resolve?
You simply have to require the class implements Serializable. Note that the asInstanceOf[Predicate[T] with Serializable] cast is a lie: it doesn't actually check value is Serializable, which is why the second case doesn't produce an error immediately during the cast, and the last one "succeeds".
But I would create a single object (maybe to broadcast) for testing.
You can't. Broadcast or not, deserialization will create new objects on worker nodes. But you can create only a single instance on each partition:
var filtered = rdd.mapPartitions { iter =>
val tester = Class.forName(qualifiedName).newInstance()
.asInstanceOf[Predicate[T]]
iter.filter(tester.test)
}
It will actually perform better than serializing the tester, sending it, and deserializing it would, since it's strictly less work.
I'm learning scala. I'm trying to find an easy way for turing JSON String to Scala case class instance. Java has wonderful library called Google Gson. It can turn java bean to json and back without some special coding, basically you can do it in a single line of code.
public class Example{
private String firstField
private Integer secondIntField
//constructor
//getters/setters here
}
//Bean instance to Json string
String exampleAsJson = new Gson().toJson(new Example("hehe", 42))
//String to Bean instance
Example exampleFromJson = new Gson().fromJson(exampleAsJson, Example.class)
I'm reading about https://www.playframework.com/documentation/2.5.x/ScalaJson and can't get the idea: why it's so complex is scala? Why should I write readers/writers to serialize/deserialize plain simple case class instances? Is there easy way to convert case class instance -> json -> case class instance using play json api?
Let's say you have
case class Foo(a: String, b: String)
You can easily write a formatter for this in Play by doing
implicit val fooFormat = Json.format[Foo]
This will allow you to both serialize and deserialize to JSON.
val foo = Foo("1","2")
val js = Json.toJson(foo)(fooFormat) // Only include the specific format if it's not in scope.
val fooBack = js.as[Foo] // Now you have foo back!
Check out uPickle
Here's a small example:
case class Example(firstField: String, secondIntField: Int)
val ex = Example("Hello", 3)
write(ex) // { "firstField": "Hello", "secondIntField" : 3 }
I'm moving from a very hard coded Java implementation to a very modular Scala implementation and I've gotten stuck translating a part of my application.
The function I'm looking at produces a message from a format string. It looks up the relevant information in a database and uses it to format the string.
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;
}
So, on the Scala side of things, I've tried to implement the different types using case objects which all extend from a base Type.
sealed class Type(val name: String)
case object NewFoo extends Type("New Foo")
case object BarShared extends Type("Bar Shared")
Problem is, with my application being modular, in my MessageService I don't have access Foo.findById, Bar.findById or Baz.findById. What I would like it to receive the appropriate strings in the parameter list, but as you can see, the number of parameters varies based on the Type. I could make the parameters optional, but then anyone calling the function needs to know which parameters are necessary based on the type, and I don't like that. I suppose I could have a different function name for each type, but I'd rather not, if there's a better way.
I think you may need to encode the knowledge of formatting a Type in that type. If your aim is to keep the MessageService agnostic to whatever data may come in, you could e.g. require each type to format itself, such as:
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}"
}
}
Then your MessageService would only know about the MessageType interface, and implementations thereof would be provided in different modules. Note that you likely would need to allow each module to register its MessageTypes against the MessageService at startup.
It seems weird to me that this getHumanizedMessage() was one single method to begin with. Because of your switch statement, you do two completely different things in one function. Why don't you split them up?
You can write:
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)
You can still use a sealed implementation for an easy match statement, you just need to have an abstract class as the base.
sealed abstract class MessageType {
val name: String
def findById[A](relatedId: Long): A
}
You can then extend case objects or case classes depending on your use cases:
case object NewFoo extends MessageType {
val name: String = "NewFoo"
def findById(relatedId: Long): NewFoo = {...}
}
or if you want to provide arguments:
case class BarShared(defaultName: String) extends MessageType {
val name: String = defaultName
def findById(relatedId: Long) BarShared = {...}
}
With the sealed class your match statement doesn't need a default, unless you define it as an extension.
I have some classes and for some reason I need a procedure that create some variables of that class dinamically...
Let's assume I have this code:
for (int i = 0 ; i < 5 ; i++)
{
....
POP tmp = new POP();
tmp = (POP) ast.convert(aso, POP.class);
}
I want that the POP class is set dinamically... I almost achieved what I want except for the casting from object to class, I do not know how to write it...
String className = "POP";
Class cl = Class.forName(className);
Class cl2 = POP.class;
cl = (??????) ast.convert(aso, cl2);
How can I solve it?
In your second code snippet, cl will actually be Class<POP> but cl2 is Class<String>, which I guess is not what you expect. Assuming you are coding in Java 5 or newer, you should not use the raw types (Class instead of Class<?>), this will make your code safer and easier to read.
Also note that you have to use the fully qualified class name, and not just the simple name of your classes. For example
Class.forName("String"); // Won't work
Class.forName("java.lang.String"); // Is what you need.
When you have a Class instance you can use reflection to create new instances dynamically:
Class<?> cl2 = ... ;
// If the class has a no-arg visible constructor
Object foo = cl2.newInstance();
// Or using an explicit constructor (here with an integer and a String as arguments)
Constructor<Class<?>> cons = cl2.getConstructor(Integer.class, String.class);
Object bar = cons.newInstance(1, "baz");
But maybe what you are trying to achieve could be done using the Abstract Factory pattern ? You provide an object that is able to create instances of the type that you want, and you can choose the factory to use based on the class name.
http://c2.com/cgi/wiki/wiki?AbstractFactoryPattern