in scala, i have a base class and a number of child classes. without adding code to a child class or changing the instantiation of a child class, i would like the base class to be able to call some code both before and after the child constructor is executed. before is easy since the base class constructor is called before the child's, but i don't see a way to handle the after case. as a bit of example code:
class A {
// do some stuff before child constructor is called
// ...
// do some other stuff after child constructor is called
// this could be a method or inline in the constructor, doesn't matter.
}
class B extends A { // stuff happens in between }
class C extends A { // stuff happens in between }
etc
val b = new B // everything happens inside, no other method call needed
is this behavior possible? thanks.
If you use Scala 2.9, you can arrange something like this:
class A {
println("Hi")
}
class B extends A with DelayedInit {
private[this] var count = 0
println("Hey")
def delayedInit(x: => Unit) {
x
count += 1
if (count==2) { println("There") }
}
}
class C extends B { println("Ho") }
class D extends C { println("Ha") }
This takes advantage of the new DelayedInit trait which sends delayed constructors from the current and all child classes to a delayedInit method. Unfortunately, since there is not a termination signal, you're limited to skipping a single constructor. So for C, we get:
scala> new C
Hi
Hey
Ho
There
where the "There" block has magically appeared after the "Ho" block from C. Unfortunately if you extend C, the new initialization happens last:
scala> new D
Hi
Hey
Ho
There
Ha
(You don't really need A there...I just put it there to illustrate what happens with superclasses.)
An 'end of concrete class' callback is possible,
the code below outputs :
hello
world1
world2
world3
end of the worlds !
trait A extends DelayedInit {
def delayedInit(body: => Unit) = {
body
println("end of the worlds !")
}
}
trait B extends A { println("hello") }
trait C extends B { println("world1") }
trait D extends C { println("world2") }
object Zozo extends D {
println("world3")
}
Related
I am relatively new to scala so please bear me if I asked silly questions.
I have a requirement where I need to invoke a method run time.
I have a trait which is being extended by two classes
trait Animal {
def walk():DataFrame
}
This is extended by two classes.
class Dog(sparkSession: SparkSession) extends Animal {
def walk():DataFrame = {
.............
}
}
class Cat(sparkSession: SparkSession) extends Animal {
def walk():DataFrame = {
.............
}
}
Now from a config file I will get a list of these class names
Lets say like this
val animals = ["com.xy.Dog","com.xy.Cat"]
I need to invoke these classes and execute walk methods.
Can I do something like this?
animals.forEach{ animalString =>
val animalObject = Class.forName(animalString ).newInstance().asInstanceOf(Animal)
animalObject.walk
}
There are a few issues, let's take them one by one:
To build a list in scala you need to do:
val animals = List("com.xy.Dog", "com.xy.Cat")
The forEach method is actually foreach, so there's a small typo. Finally, when you call the newInstance you should get the appropriate constructor before that, otherwise it will use the default one.
animals.foreach { animalString =>
val animalObject = Class.forName(animalString)
.getConstructor(classOf[DataFrame]) // Get the constructor for a DataFrame argument
.newInstance(dataframe) // Pass the dataframe instance
.asInstanceOf[Animal]
animalObject.walk
}
I've made a couple of small changes to the code for you to see it working. You can run the app to see the output:
class Dog extends Animal {
def walk(): Unit = { println("I'm a dog.") }
}
class Cat extends Animal {
def walk(): Unit = { println("I'm a cat.") }
}
object AnimalTest extends App {
val animals = List("com.xy.Dog", "com.xy.Cat")
animals.foreach { animalString =>
val animalObject = Class.forName(animalString)
.newInstance()
.asInstanceOf[Animal]
animalObject.walk
}
}
Note that I've removed the constructor arguments here to easily build instances. The rest is about the same. I hope this helps you.
I want to make a copy of B, however I do not want to repeat the copying in the subclass (B) that goes on in the superclass (A).
The solution below is what I cooked up. But I don't like it because it is not a copy constructor and because it is mutating state (vars everywhere).
Scala allows direct call to super only from the primary constructor so I had no idea how to create a copy constructor for B without repeating the copying code present in the superclass (A).
Any suggestions on how to implement a DRY copy constructor or a more elegant way to copy?
class A {
var fieldA=1
def copyFieldsInto(a:A):Unit={
a.fieldA=fieldA
}
}
class B extends A{
var fieldB=2
def copyFieldsInto(b:B):Unit=
{
super.copyFieldsInto(b)
b.fieldB=fieldB
}
}
object Test extends App{
println("hello")
val b=new B
b.fieldA=3
b.fieldB=4
val b_copy=new B
b.copyFieldsInto(b_copy)
println(b.fieldB,b.fieldA)
println(b_copy.fieldB,b_copy.fieldA)
}
this will print :
hello
(4,3)
(4,3)
If I understand you correctly, then this is what you want?
class A(val aVal: Int) {
def this(a:A)={
this(a.aVal)
}
}
class B(aVal:Int, val bVal:Int) extends A(aVal){
def this(b:B) = {
this(b.aVal, b.bVal)
}
}
object Test extends App{
println("hello")
val b=new B(3,4)
val b_copy=new B(b)
println(b.bVal,b.aVal)
println(b_copy.bVal,b_copy.aVal)
}
I need a smart mechanism for component composition which allows mixed in traits to initialize after the composed component. The following throws a NullPointerException:
class Component {
def addListener(pf: PartialFunction[Any, Unit]) {}
}
trait DynamicComponent {
protected def component: Component
component.addListener {
case x =>
}
}
class Foo extends DynamicComponent {
protected val component = new Component
}
new Foo // -> NullPointerException
The following things are not options for me:
Using protected lazy val component; that would produce an avalange of dozens of vals needing to become lazy, something I do not want.
Putting addListener in a method, e.g. initDynamic(); because I will be mixing in many traits, and I don't want to remember to call half a dozen initFoo() methods.
Using DelayedInit. This doesn't work with traits, at least according to the scaladocs.
I could live with a single init() call, but only under the following conditions:
all mixed in traits can easily declare to be invoked in this one single call
it is a compile error to forget the init() statement.
You can delay the initialization of a trait by by using early definitions. (See section 5.1.6 of the scala language specification)
class Foo extends {
protected val component = new Component
} with DynamicComponent
It's even clunkier than your solution, but you can always require the creation of a val that must be set with the init() method. You could choose to not do it last and get an error at runtime, but at least you won't forget it entirely:
class Component {
def addListener(pf: PartialFunction[Any, Unit]) {
println("Added")
}
}
trait Dyn {
protected def component: Component
protected val initialized: Init
class Init private () {}
private object Init { def apply() = new Init() }
def init() = { component.addListener{ case x => }; Init() }
}
class Foo extends Dyn {
protected val component = new Component
protected val initialized = init()
}
No cheating!:
> class Bar extends Dyn { protected val component = new Component }
<console>:12: error: class Bar needs to be abstract, since value
initialized in trait Dyn of type Bar.this.Init is not defined
class Bar extends Dyn { protected val component = new Component }
The advantage this has is if you need multiple things to be in place before you initialize all of them cooperatively, or if your Component class is final so you can't mix in anything else.
AN idea could be to use the trick described here:
Cake pattern: how to get all objects of type UserService provided by components
All your components that should be initialized could be registered in some Seq[InitializableComponent]. And then you could initialize all registered components with a foreach.
No component will be forgotten in that Seq because they are registered automatically, but you can still forget to call the foreach anyway...
Here is one idea (I am happy to read about other suggestions):
class Component {
def addListener(pf: PartialFunction[Any, Unit]) {
println("Added")
}
}
trait DynamicComponentHost {
protected def component: Component with DynamicPeer
protected trait DynamicPeer {
_: Component =>
addListener {
case x =>
}
}
}
class Foo extends DynamicComponentHost {
protected val component = new Component with DynamicPeer
}
new Foo
So basically I am forcing the component to mix in a type that can only be provided by the mixed in trait. Reasonable? Looks a bit too complicated in my eyes.
I have the following code:
trait A {
import org.somepackage.C._
}
class B extends A {
def getValue = value
^^^^^
}
object C {
var value = 5
}
The value in class B is not visible what means that the inherent import of class A was not inherited by B, although the value is perfectly visible inside A. How to achieve the effect of also inheriting imports so I could avoid explicitly importing same things in multiple classes where trait A mixes in?
Imports not being a first class entity do not exhibit the behavior you are expecting. You can instead restructure your design thusly to achieve something close:
trait A with C {
}
class B extends A {
def getValue = value // Now this will work.
}
trait C {
var value = 5
}
object C extends C
This idiom is used in Scalaz 6 to tax users with as few imports as possible.
I have the following class in my mind:
abstract class MyClass (data: MyData) {
def update(): MyClass = {
new MyClass(process())
}
def process(): MyData = {
...
}
}
However, abstract classes cannot be instantiated so the line new MyClass(process()) is an error. My question is - is there any way to tell the compiler that in case of each of the child classes of MyClass I want to create an object of exactly that child class? It seems an overkill to write this method awhole in all child classes. Playing with type parameters of the class or method I could not acheive that myself.
How about something like this? MyClass is parametrized with the concrete type. Of course, all concrete classes have to implement a method that actually returns a new instance of Self.
trait MyClass[+Self <: MyClass[Self]] {
def update(): Self = {
makeNew(process())
}
def process(): MyData = {
// ...
}
protected def makeNew(data: MyData): Self
}
class Concrete0 extends MyClass[Concrete0] {
protected def makeNew(data: MyData) = new Concrete0
}
class RefinedConcrete0 extends Concrete0 with MyClass[RefinedConcrete0] {
override protected def makeNew(data: MyData) = new RefinedConcrete0
}
Credit: IttayD’s second update to his answer to this question.
To completly avoid implementing almost identical method in all subclasses you would need to use reflection. I guess that would be your last resort if you have chosen Scala.
So here is how to minimize the repetitive code:
// additional parameter: a factory function
abstract class MyClass(data: MyData, makeNew: MyData => MyClass) {
def update(): MyClass = {
makeNew(process())
}
def process(): MyData = {
...
}
}
class Concrete(data: MyData) extends MyClass(data, new Concrete(_))
This way you repeat only the shortest fragment required to instantiate the subclass.