Lets say I have the following structure:
src
- main
- scala
- model
- One.scala
- Two.scala
- main
- Test.scala
where Test.scala extends App and takes in a parameter:
object Test extends App {
val param: String = args.head
// Based on param, I want to use either One or Two?
}
// sbt run Two
How do i use definitions in either One.scala or Two.scala depending on the runtime value of param.
Appreciate any/all inputs..
Make sure that One and Two share some common interface, choose the instance of this interface at runtime, then import the members of the instance:
trait CommonInterface {
def foo(): Unit
}
object One extends CommonInterface { def foo() = println("1") }
object Two extends CommonInterface { def foo() = println("2") }
object Main extends App {
// check args etc...
val ci = if (args(0) == "one") One else Two
import ci._
// do something with `foo` here
foo()
}
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'm trying to define a reusable trait that expects a value to be in an outer scope. I can define the trait inside the outer scope and it will work, but won't be reusable. When I move the trait to a separate scope, the trait can't access the value and I haven't found a way to declare it as present in the outer scope of the type the trait is being mixed in to.
The closest I have got so far is this:
import javafx.beans.property.ObjectProperty
import akka.actor.{Props, ActorSystem}
import javafx.event.EventHandler
import javafx.stage.{WindowEvent => JWindowEvent}
import scalafx.application.{Platform, JFXApp}
import scalafx.scene.Scene
import scalafx.scene.canvas.Canvas
import scalafx.scene.paint.Color
object MicroServicesApp extends JFXApp {
implicit val system = ActorSystem("system")
val canvas = new Canvas {
width = 1200
height = 900
}
stage = new MicroServicesPrimaryStage with AutomaticMicroServicesWindowCloser {
title.value = "Map Viewer"
scene = new Scene {
fill = Color.LightGreen
content = canvas
}
}
}
class MicroServicesPrimaryStage(implicit val actorSystem: ActorSystem) extends JFXApp.PrimaryStage with MicroServices {
}
/**
* A class enabled with a micro-services actor system.
*/
trait MicroServices {
def actorSystem: ActorSystem
}
/**
* An automatic window closer for a ScalaFX and Akka micro-services application.
*
* When this trait is mixed in to a class with the MicroServices trait and the onCloseRequest property,
* the onCloseRequest property will be initialized with a useful default event handler that shuts down
* the Akka actor system as well as the ScalaFX platform.
*/
trait AutomaticMicroServicesWindowCloser extends MicroServicesWindowCloser {
def onCloseRequest: ObjectProperty[EventHandler[JWindowEvent]]
def onCloseRequest_=(handler: EventHandler[JWindowEvent]): Unit
onCloseRequest = closeRequest()
}
/**
* A window closer for a ScalaFX and Akka micro-services application.
*/
trait MicroServicesWindowCloser extends MicroServices {
def closeRequest(): EventHandler[JWindowEvent] = new EventHandler[JWindowEvent] {
override def handle(e: JWindowEvent)
{
println("... closing application.")
actorSystem.shutdown()
Platform.exit()
}
}
}
It gets pretty close to what I'm after, the only give-away is the need for the client code to declare the value in the outer scope to be implicit. Ideally I would like the client code to mix-in the trait without changing anything else.
In the example I can use 'system' from within 'MicroServicesPrimaryStage', but not from within the mixed-in trait. I think this is because 'system' is in scope but not considered to be defined as a member of 'MicroServicesPrimaryStage'.
I could create an alias for 'system' with a val or a def and make it work that way, but that also means an extra step in modifying the client code. It would be nice if the trait could require a definition for 'system' and be able to find it in the outer scope at the point where the trait is mixed-in.
Is this possible?
Edit 1
These two println statements illustrate the cause of my confusion:
stage = new MicroServicesPrimaryStage with AutomaticMicroServicesWindowCloser {
println(s"val system is accessible from outer scope: $system ...") // compiles
println(s"... but is not mixed-in to MicroServicesPrimaryStage as ${this.system}.") // does not compile
...
I don't think the cake pattern can solve this on its own, because the question is about how the type system interacts with definitions in outer scopes.
Edit 2
SBT file for use with Java 8:
name := "workspace-sbt"
version := "1.0"
scalaVersion := "2.11.4"
resolvers += Opts.resolver.sonatypeSnapshots
libraryDependencies ++= Seq("org.scalatest" % "scalatest_2.11" % "2.2.1" % "test",
"org.scalafx" %% "scalafx" % "8.0.20-R7-SNAPSHOT",
"com.typesafe.akka" %% "akka-actor" % "2.3.7")
You are mistaken:
"In the example I can use 'system' from within 'MicroServicesPrimaryStage', but not from within the mixed-in trait. I think this is because 'system' is in scope but not considered to be defined as a member of 'MicroServicesPrimaryStage'."
This is not true. You can certainly use super class members as definitions for abstract members of mixed in traits. Consider this:
trait Foo {
def foo: String
def printFoo = println(foo)
}
class FooBar(val foo)
object FooBar {
def main(argv: Array[String]) = new FooBar("foo") with Foo printFoo
}
This compiles and will print "foo" if run. Is it not what you are trying to do?
Maybe that's what you're looking for:
scala> abstract class Aaaa(implicit val a: Int)
defined class Aaaa
scala> class Kkk extends Aaaa
<console>:9: error: could not find implicit value for parameter a: Int
class Kkk extends Aaaa
^
scala> implicit val a = 5
a: Int = 5
scala> class Kkk extends Aaaa
defined class Kkk
scala> new Kkk
res12: Kkk = Kkk#1a79ef3
scala> res12.a
res13: Int = 5
Let's imagine, that Int is an ActorSystem)
This value will be accessible from both Kkk and Aaaa. But implicit value should be defined in the scope, where you actually mixin Aaaa.
Sorry if I, too, am missing something.
This is just the classic charlotte cake pattern.
Or, maybe you're asking for a fruit cake, with an extra surprise in the next layer. (Maybe a King's cake is a better metaphor.)
package cakesample
// something useful
trait Something {
def thing: String
}
// a trait requiring something
trait Needy { _: Something =>
def theThingIs: String = thing
}
// another trait that uses something
trait User { _: Something =>
def use: String = thing * 2
}
// fruit cake fixings
case class Widget(w: String)
trait WidgetFramework {
// used by the framework
def widget: Widget
trait WidgetCog {
def run() = Console println s"Running ${widget.w}"
}
}
// sample usage
object Test extends App with Something with Needy with User with WidgetFramework {
// normal cake, a charlotte
def thing = "hello, world"
Console println s"$theThingIs: $use"
// a fruit cake
// define a widget
val widget = Widget("my widget")
// to be used by an object implementing a trait
object client extends WidgetCog
client.run()
}
I don't know why it should be yellow, except yellow is funnier than pound in this context. (Update: charlotte is more technically correct; but in the spirit of the season, a fruit cake is maybe what you're after.)
Parametrized components work well with the cake pattern as long as you are only interested in a unique component for each typed component's, example:
trait AComponent[T] {
val a:A[T]
class A[T](implicit mf:Manifest[T]) {
println(mf)
}
}
class App extends AComponent[Int] {
val a = new A[Int]()
}
new App
Now my application requires me to inject an A[Int] and an A[String], obviously scala's type system doesn't allow me to extends AComponent twice. What is the common practice in this situation ?
I think the AComponent doesn't need to be parameterized itself. So loose the type parameter and change this into
trait AComponent {
val aInt: A[Int]
val aStr: A[String]
class A[T](implicit mf:Manifest[T]) {
println(mf)
}
}
class App extends AComponent {
val aInt = new A[Int]()
val aStr = new A[String]()
}
if you want to be able to provide instances for Int and String
Hey guys,
im working on a project in scala and i encountered very weird problem. This is a part of the code :
class Entity(val id:String){
override def toString = id
}
class RequirementType
case class DependsEither(t:List[(Entity,Int)]) extends RequirementType
case class Depends(t:(Entity,Int)) extends RequirementType
class BuildableEntity(override val id:String,
val mineralCost:Int,
val gasCost:Int,
val buildTime:Int,
val buildCount:Int,
val supplyCount:Int,
val req:List[RequirementType],
val onBuildStart: GameState => GameState,
val onBuildFinish: GameState => GameState
)extends Entity(id)
class SimpleBuilding(id:String,
mineralCost:Int,
gasCost:Int,
buildTime:Int,
req:List[RequirementType]
) extends BuildableEntity(id,mineralCost,gasCost,buildTime,1,0,req:::List(ConsumesOnStart((Drone,1))),{s=>s},{x=>x})
object SpawningPool extends SimpleBuilding("spawningPool",200,0,65,List(DependsEither(List((Hatchery,1),(Lair,1),(Hive,1)))))
object Lair extends SimpleBuilding("lair",150,100,80,List(ConsumesOnFinish(Hatchery,1),Depends(SpawningPool,1)))
object InfestationPit extends SimpleBuilding("infestationPit",100,100,50,List(DependsEither(List((Lair,1),(Hive,1)))))
Now, when i call println(Lair.req), it sometimes prints as
List(ConsumesOnFinish((hatchery,1)), Depends((null,2)), ConsumesOnStart((drone,1)))
and sometimes as
List(ConsumesOnFinish((hatchery,1)),
Depends((spawningPool,2)), ConsumesOnStart((drone,1)))
Please, if anyone has any idea about what could be going wrong, i would love you for ever. I have no clue why is it act as it does. I have more extensions of SimpleBuilding but they seem to be working properly
EDIT:
I should also mention that the outcome changes after compilation. I mean that when i run unit test it sometimes appear as null and sometimes as proper instance.
This is indeed a case of circular dependency and initialization. Here is a shorter version of your issue:
class X(val x: List[X])
object A extends X(List(B))
object B extends X(List(A))
object Main {
def main(args:Array[String]) {
println("A.x: " + A.x)
println("B.x: " + B.x)
}
}
This will print this:
$ scala -cp classes Main
A.x: List(B$#143c8b3)
B.x: List(null)
You can use by names parameter to allow object construction to finish before you use it:
class X(x0: => List[X]) {
lazy val x = x0
}
object A extends X(List(B))
object B extends X(List(A))
The fix works on the small test case:
$ scala -cp classes Main
A.x: List(B$#1feca64)
B.x: List(A$#6d084b)
Based on this you may want to change req:List[RequirementType] to req0: => List[RequirementType] and add a lazy val req = req0.
If that works for you, we should retitle the question to mention object initialization and circular dependencies. Note this is very similar to this question/answer.
Lair use SpawningPool in its constructor and reciprocally. But at that time, the other doesn't exists.
You've got recursive definitions in constructors, and although I believe that is supported, it looks like something's going wrong. Can you try lazy vals instead and see if the problem goes away? That is,
object X extends C("this",that,1) { /* code */ }
becomes
lazy val X = new C("this",that,1) { /* code */ }