I was about to use case classes with named default parameters as builders. For a simple example:
case class Person(name:String)
case class PersonBob(name:String = "Bob") {
def build = Person(name)
}
val casePerson = PersonBob("case").build
But I could use methods as well:
object Builder {
def personBob(name:String = "Bob"):Person = Person(name)
}
val methodPerson = Builder.personBob("method")
Some tradeoffs:
Method approach eliminates the need to create an object for each builder...saving cycles and memory.
Method approach has a bit leaner implementation code. No advantage for the usage syntax.
Methods can't be passed in as parameters to other builders for "builder composition". Functions can, but we are talking about methods here since functions don't support parameter defaults.
Case class approach allows me to persist builder instances (not needed now).
Case class approach would facilitate building an internal DSL at some point--but I think an external DSL is ambivalent to either approach.
Other considerations? Build a better builder some other way?
Confused am I: isn't the baked-in case class factory all that you need here, or am I missing something. IOW:
scala> case class Foo(bar:String="ab")
defined class Foo
scala> val f = Foo()
f: Foo = Foo(ab)
scala> f.bar
res2: String = ab
Related
I have a working Scala application in production that is using a object which has several methods defined inside it.
There are new requirements for this application where I will have to rewrite (override) few of the methods from that object while reusing the definitions of remaining methods from that object.
How can I create a new object inheriting the original one so that I can override the definitions of a few selected methods?
A Scala object cannot inherit from another Scala object so the obvious way is not possible.
If you can modify the original object then create a class that implements all the functionality and make the original object inherit from that class. Your new object can then inherit from the same class and override the methods that you want to change. However this will create two copies of any values in the base class, so it is not suitable for an object that contains a lot of data or does any one-off initialisation.
If you cannot modify the original object then you will have to copy all the methods of the first object in your new object. vals can be copied directly. defs can be copied using eta expansion:
def v = Original.v // This is a simple value
def f = Original.f _ // This is a function value
Using def rather than val here will avoid storing multiple copies of the original values and will prevent lazy values from being computed until they are needed.
Using eta expansion will make f a function value rather than a method which may or may not be a problem depending on how it is used. If you require f to be a method then you will have to duplicate the function signature and call the original f:
def f(i: Int) = Original.f(i) // This is a method
My suggestion would be to move the code/logic to a trait or abstract class and have both objects extend these.
On the upside this would also give you better testability.
Another more hacky approach could be to not use the class/type system at all and jsut forward the methods using a new singleton objec:
scala> object A {def foo: String = "foo" ; def bar:Int = 0}
defined object A
scala> object B { def foo = A.foo; def bar = "my new impl" }
defined object B
scala> A.foo
res3: String = foo
scala> B.foo
res4: String = foo
scala> A.bar
res5: Int = 0
scala> B.bar
res6: String = my new impl
General style question.
As I become better at writing functional code, more of my methods are becoming pure functions. I find that lots of my "classes" (in the loose sense of a container of code) are becoming state free. Therefore I make them objects instead of classes as there is no need to instantiate them.
Now in the Java world, having a class full of "static" methods would seem rather odd, and is generally only used for "helper" classes, like you see with Guava and Commons-* and so on.
So my question is, in the Scala world, is having lots of logic inside "objects" and not "classes" quite normal, or is there another preferred idiom.
As you mention in your title, objects are singleton classes, not classes with static methods as you mention in the text of your question.
And there are a few things that make scala objects better than both static AND singletons in java-world, so it is quite "normal" to use them in scala.
For one thing, unlike static methods, object methods are polymorphic, so you can easily inject objects as dependencies:
scala> trait Quack {def quack="quack"}
defined trait Quack
scala> class Duck extends Quack
defined class Duck
scala> object Quacker extends Quack {override def quack="QUAACK"}
defined module Quacker
// MakeItQuack expects something implementing Quack
scala> def MakeItQuack(q: Quack) = q.quack
MakeItQuack: (q: Quack)java.lang.String
// ...it can be a class
scala> MakeItQuack(new Duck)
res0: java.lang.String = quack
// ...or it can be an object
scala> MakeItQuack(Quacker)
res1: java.lang.String = QUAACK
This makes them usable without tight coupling and without promoting global state (which are two of the issues generally attributed to both static methods and singletons).
Then there's the fact that they do away with all the boilerplate that makes singletons so ugly and unidiomatic-looking in java. This is an often overlooked point, in my opinion, and part of what makes singletons so frowned upon in java even when they are stateless and not used as global state.
Also, the boilerplate you have to repeat in all java singletons gives the class two responsibilities: ensuring there's only one instance of itself and doing whatever it's supposed to do. The fact that scala has a declarative way of specifying that something is a singleton relieves the class and the programmer from breaking the single responsibility principle. In scala you know an object is a singleton and you can just reason about what it does.
You can also use package objects e.g. take a look at the scala.math package object here
https://lampsvn.epfl.ch/trac/scala/browser/scala/tags/R_2_9_1_final/src//library/scala/math/package.scala
Yes, I would say it is normal.
For most of my classes I create a companion object to handle some initialization/validation logic there. For example instead of throwing an exception if validation of parameters fails in a constructor it is possible to return an Option or an Either in the companion objects apply-method:
class X(val x: Int) {
require(x >= 0)
}
// ==>
object X {
def apply(x: Int): Option[X] =
if (x < 0) None else Some(new X(x))
}
class X private (val x: Int)
In the companion object one can add a lot of additional logic, such as a cache for immutable objects.
objects are also good for sending signals between instances if there is no need to also send messages:
object X {
def doSomething(s: String) = ???
}
case class C(s: String)
class A extends Actor {
var calculateLater: String = ""
def receive = {
case X => X.doSomething(s)
case C(s) => calculateLater = s
}
}
Another use case for objects is to reduce the scope of elements:
// traits with lots of members
trait A
trait B
trait C
trait Trait {
def validate(s: String) = {
import validator._
// use logic of validator
}
private object validator extends A with B with C {
// all members of A, B and C are visible here
}
}
class Class extends Trait {
// no unnecessary members and name conflicts here
}
I'm trying to figure out how to .clone my own objects, in Scala.
This is for a simulation so mutable state is a must, and from that arises the whole need for cloning. I'll clone a whole state structure before moving the simulation time ahead.
This is my current try:
abstract trait Cloneable[A] {
// Seems we cannot declare the prototype of a copy constructor
//protected def this(o: A) // to be defined by the class itself
def myClone= new A(this)
}
class S(var x: String) extends Cloneable[S] {
def this(o:S)= this(o.x) // for 'Cloneable'
def toString= x
}
object TestX {
val s1= new S("say, aaa")
println( s1.myClone )
}
a. Why does the above not compile. Gives:
error: class type required but A found
def myClone= new A(this)
^
b. Is there a way to declare the copy constructor (def this(o:A)) in the trait, so that classes using the trait would be shown to need to provide one.
c. Is there any benefit from saying abstract trait?
Finally, is there a way better, standard solution for all this?
I've looked into Java cloning. Does not seem to be for this. Also Scala copy is not - it's only for case classes and they shouldn't have mutable state.
Thanks for help and any opinions.
Traits can't define constructors (and I don't think abstract has any effect on a trait).
Is there any reason it needs to use a copy constructor rather than just implementing a clone method? It might be possible to get out of having to declare the [A] type on the class, but I've at least declared a self type so the compiler will make sure that the type matches the class.
trait DeepCloneable[A] { self: A =>
def deepClone: A
}
class Egg(size: Int) extends DeepCloneable[Egg] {
def deepClone = new Egg(size)
}
object Main extends App {
val e = new Egg(3)
println(e)
println(e.deepClone)
}
http://ideone.com/CS9HTW
It would suggest a typeclass based approach. With this it is possible to also let existing classes be cloneable:
class Foo(var x: Int)
trait Copyable[A] {
def copy(a: A): A
}
implicit object FooCloneable extends Copyable[Foo] {
def copy(foo: Foo) = new Foo(foo.x)
}
implicit def any2Copyable[A: Copyable](a: A) = new {
def copy = implicitly[Copyable[A]].copy(a)
}
scala> val x = new Foo(2)
x: Foo = Foo#8d86328
scala> val y = x.copy
y: Foo = Foo#245e7588
scala> x eq y
res2: Boolean = false
a. When you define a type parameter like the A it gets erased after the compilation phase.
This means that the compiler uses type parameters to check that you use the correct types, but the resulting bytecode retains no information of A.
This also implies that you cannot use A as a real class in code but only as a "type reference", because at runtime this information is lost.
b & c. traits cannot define constructor parameters or auxiliary constructors by definition, they're also abstract by definition.
What you can do is define a trait body that gets called upon instantiation of the concrete implementation
One alternative solution is to define a Cloneable typeclass. For more on this you can find lots of blogs on the subject, but I have no suggestion for a specific one.
scalaz has a huge part built using this pattern, maybe you can find inspiration there: you can look at Order, Equal or Show to get the gist of it.
In Scala, if we have
class Foo(bar:String)
We can create a new object but cannot access bar
val foo = new Foo("Hello")
foo.bar // gives error
However, if we declare Foo to be a case class this works:
case class Foo(bar:String)
val foo = Foo("hello")
foo.bar // works
I am forced to make many of my classes as case classes because of this. Otherwise, I have to write boilerplate code for accessing bar:
class Foo(bar:String) {
val getbar = bar
}
So my questions are:
Is there any way to "fix" this without using case classes or boilerplate code?
Is using case classes in this context a good idea? (or what are the disadvantages of case classes?)
I guess the second one deserves a separate question.
Just use val keyword in constructor to make it publicly accessible:
class Foo(val bar:String) {
}
As for your question: if this is the only feature you need, don't use case classes, just write with val.
However, would be great to know why case classes are not good.
In case classes all arguments by default are public, whereas in plain class they're all private. But you may tune this behaviour:
scala> class Foo(val bar:String, baz: String)
defined class Foo
scala> new Foo("public","private")
res0: Foo = Foo#31d5e2
scala> res0.bar
res1: String = public
scala> res0.baz
<console>:10: error: value baz is not a member of Foo
res0.baz
And even like that:
class Foo(private[mypackage] val bar:String) {
// will be visible only to things in `mypackage`
}
For case classes (thanks to #JamesIry):
case class Bar(`public`: String, private val `private`: String)
You can use the BeanProperty annotation to automatically generate java-like getters
import scala.reflect.BeanProperty
case class Foo(#BeanProperty bar:String)
Now Foo has a getBar method that returns the bar value.
Note though that this is only useful if you have a good reason to use java-like getters (typical reasons being that you need your class to be a proper java bean, so as to work with java libraries that expect java beans and use reflection to access the bean's properties).
Otherwise, just access the bar value directly, this is "the scala way".
See http://www.scala-lang.org/api/current/index.html#scala.reflect.BeanProperty
In Scala, you can "add new methods" to existing classes by creating wrapper class and using "implicit def" to convert from the original class to the rich wrapper class.
I have a java library for graphics that uses plenty of constructors with looong lists of floats. I would love to add new constructors to these classes with rich wrapping but this doens't seem to work like the above for methods. In other words, I would like to have simpler constructors but still to be able to keep using the original class names and not some wrapper class names but currently I see no other options.
Ideas?
Sounds like you want to use Scala's apply(...) factory methods, which you build in to the companion object for your class.
For example, if you have:
class Foo(val bar: Int, val baz: Int) {
... class definition ...
}
You could add (in the same file):
object Foo {
def apply(bar: Int) = new Foo(bar, 0)
}
With this in hand, creating a new Foo instance, just providing the bar parameter, is as easy as
val myBar = 42
val myFoo = Foo(myBar) // Note the lack of the 'new' keyword.
This will result in myFoo being assigned an instance of Foo where bar = 42, and baz = 0.
Yes, you need a combination of the "Pimp my Library" approach and an apply factory method.