Is it possible to have a trait be a singleton?
What I am trying to achieve is to have a clean and lightweight API I can extend throughout my application like the following:
trait SingletonTrait {
// element I wish to be unique throughout my application
val singletonElement = ///
...
}
// uses *singletonElement*
object MainApplication extends SingletonTrait {
...
}
// uses *singletonElement*
class SomeClass(...) extends SingletonTrait {
...
}
In the same idea implied by a getOrCreate() function that would retrieve an existing instance of an element if one already exists or creates it otherwise.
Maybe just create value in companion object and reference it in trait?
trait SingletonTrait {
final lazy val singletonElement = SingletonTrait.SingletonElement
}
object SingletonTrait {
lazy val SingletonElement = {
println("Creating singleton element!")
"singleton element"
}
}
// uses *singletonElement*
class SomeClass() extends SingletonTrait {
println(s"Using ${singletonElement} in class.")
}
new SomeClass()
new SomeClass()
new SomeClass()
It prints:
Creating singleton element!
Using singleton element in class.
Using singleton element in class.
Using singleton element in class.
Technically you could do this like so
object SingletonElement {
var count = 0
}
trait SingletonTrait {
final val singletonElement = SingletonElement
}
object MainApplication extends SingletonTrait {
singletonElement.count = singletonElement.count + 1
}
class SomeClass extends SingletonTrait {
singletonElement.count = singletonElement.count + 1
}
We can test that the same object is used like so
new SomeClass
MainApplication
SingletonElement.count
which should output
res2: Int = 2
which shows the same SingletonElement was used.
Related
I would like to write a Scala test which checks the exact class of an object created with factory method.
class Base { }
class Derived extends Base { }
class TestSpec {
test("test instance class") {
val result = new Derived()
// I want to check that result is exactly Derived type
result should be a[Derived]
result should not be a[Base]
}
}
I'm looking for something to test if object returned from my factory method for specific parameters is always base class. So it would be something like this is C#:
public class Base { }
public class Derived : Base { }
public class Program
{
public static void Main(string[] args)
{
var baseObject = new Base();
var derivedObject = new Derived();
var baseResult = baseObject.GetType().IsSubclassOf(typeof(Base));
var derivedResult = derivedObject.GetType().IsSubclassOf(typeof(Base));
Console.WriteLine(string.Format("Base is subclass of Base: {0}\nDerived is subclass of Base: {1}", baseResult, derivedResult));
}
}
you can do this :
class A{}
class B extends A{}
val result = new B()
result.getClass.getName shouldEqual classOf[B].getName
result.getClass.getName.equals(classOf[A].getName) shouldBe false
new Derived() will always be an instance of Base as it inherits from Base, which means:
new Derived().isInstanceOf[Base]
will return true.
But the opposite is false: Base won't be an instance of Derived.
Thus, to check if it's the Base class (and not the Derived class), you can use these two combined conditions:
new Base() should not be a[Derived]
new Base() shouldBe a[Base]
and to check if it's the Derived class, the following is enough:
new Derived() shouldBe a[Derived]
I have a Scala application, where pretty much every object extends a specific trait, which holds all the main functions and variables used by pretty much the entire system.
I want to add a --testing flag to my app's command line variables, which will shift the the results of some of the functions in the trait.
Putting it simply, I'd like the variable accepted in the main to have an affect that alters something in the trait before it is extended by the objects - without sending it explicitly to all objects.
Any ideas how that can be performed?
I doubt you really want to dynamically modify a trait, and I am not sure if it possible that all your classes inheriting that trait would be affected. I don't know enough about the compiler and byte code.
A way to accomplish something similar would be to have your trait take a parameter, and make your trait act conditionally on the parameter.
trait Foo {
val testing: Boolean
def fn1(): Unit = {
if (testing) {
println("testing")
} else {
println("production")
}
}
}
class Bar(val testing: Boolean) extends Foo {
def fn2(): Unit = {
fn1()
}
}
new Bar(true).fn2()
new Bar(false).fn2()
Your question is broad and this is just my 5 cents.
Update
trait Foo {
def fn1(): Unit = {
if (Foo.testing) {
println("testing")
} else {
println("production")
}
}
}
object Foo {
var testing: Boolean = false
}
class Bar extends Foo {
def fn2(): Unit = {
fn1()
}
}
object SOApp extends App {
new Bar().fn2()
Foo.testing = true
new Bar().fn2()
}
Consider passing the 'testing' flag to the trait's initializer block like this:
trait MyTrait {
var testMode: Boolean = _
def doSomething(): Unit = {
if (testMode)
println("In Test Mode")
else
println("In Standard Mode")
}
}
// IMPORTANT: Your best bet would be to create some Config object
// that is loaded and initialized in a main method.
// Define test-specific Config class:
case class Config(testMode: Boolean) {
def isTestMode: Boolean = this.testMode
}
// Instantiate in main method:
val config = new Config(true)
// Later, extend the trait:
class MyObj extends MyTrait { testMode = config.isTestMode() }
// Then just invoke
new MyObject().doSomething()
Consider the following program. There are a bunch of type definitions, and a trait, and an object extending this trait.
This is a very simplified version of my program. The type definitions and trait are inside the program, and the user is supposed fill out the details inside the object:
/* ---------------------------------------------------*/
/** the internal program */
case class Type1()
case class Type2()
case class Type3()
trait aTrait {
// some stuff here
}
/* ---------------------------------------------------*/
/** user side */
object samepleObject extends aTrait {
val object1 = new Type1()
val object2 = new Type1()
val object3 = new Type2()
val object4 = new Type3()
// list of all objects here
// this definition should be populated automatically.
val all = List(object1, object2, object3, object4)
}
The user is supposed to define a set of variables (of possibly different types). There is a variable all which is a List of all variables user has defined. The question is it possible to define and populate this variable automatically (possibly inside the aTrait trait)?
This reminds me a bit of what Enums. I think you can only achieve something like that with a mutable state in your object or aTrait. That also means handlinf thread safety.
You could do something like
/* ---------------------------------------------------*/
/** the internal program */
case class Type1()
case class Type2()
case class Type3()
import scala.collection.mutable
trait aTrait {
private[this] var registry = mutable.ListBuffer.empty[Value[_]]
case class Value[T](value: T) {
registry.synchronized { registry :+= this }
}
def all: List[Value[_]] = registry.toList
}
/* ---------------------------------------------------*/
/** user side */
object sampleObject extends aTrait {
val object1 = Value(new Type1())
val object2 = Value(new Type1())
val object3 = Value(new Type2())
val object4 = Value(new Type3())
}
val test = sampleObject.all
> test: List[sampleObject.Value[_]] = List(Value(Type1()), Value(Type1()), Value(Type2()), Value(Type3()))
However, I do not guarantee concurrency-issuelessness
I have the following class setup:
class MyClass {
class MyInnerClass(memberVar: String)
def getAInner: MyInnerClass = {
new MyInnerClass("hello")
}
}
Then I have the following code outside of the class:
def myFunction = {
val a = new MyClass
val b = a.getAInner.memberVar // value memberVar is not a member of a.MyInnerClass
}
Why is this?
You need to add the keyword val to make memberVar public otherwise it's a private value:
class MyClass {
class MyInnerClass(val memberVar: String)
def getAInner: MyInnerClass = {
new MyInnerClass("hello")
}
}
#Noah's answer is totally correct, but I would also throw out the option of using case class. See here for some of the sugar it provides. I use it almost reflexively. In your example, it would be:
object MyClass {
case class MyInnerClass(memberVar: String)
def getAInner: MyInnerClass = {
new MyInnerClass("hello")
}
}
def myFunction = {
val b = MyClass.getAInner.memberVar
}
I tend to do it this way because invariably, I want to take advantage of the sane defaults case class provides.
I also chose to use object for the outer type, because it doesn't have any parameters, although you may have just done that for simplicity's sake.
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.