How do I access an overridden data member in Scala? - scala

How do I call an overridden data member in Scala? Here's an example from a worksheet -- I'd like to do something like:
trait HasWings {
def fly() = println("I'm flying!")
val wingType = "Thin"
}
class Bee extends HasWings {
override def fly() = {
println("Buzzzz! Also... ")
super.fly() // we can do this...
}
override val wingType = "Translucent and " + super.wingType // ...but not this!
}
val bumble = new Bee()
bumble.fly()
println(s"${bumble.wingType}")
But I get the error, super may not be used on value wingType. How can I override the data member while still getting access to it? There are workarounds, like:
Not overriding the superclass value
Declaring the superclass value as a method
But I'm curious if I can have my override and my superclass data member access.
Thanks!

As the compiler tells you, scala does not allow to use super on a a val.
If you need this, you can refactor your code to use a def that is used to initialize the val. Then you can override the def instead:
trait HasWings {
def wingType0: String = "Thin"
val wingType = wingType0
}
class Bee extends HasWings {
override def wingType0 = "Translucent and " + super.wingType0
}

No, that is not possible at all.

Related

Type class pattern: simulacrum boosted method not found

I have a requirement to be able to count number of times AtomicReference[V].get is called in a class that has as field an array of wildcarded atomic references.
To that end, first, I've extended java's AtomicReference[V]:
import java.util.concurrent.atomic.{AtomicInteger => AInt, AtomicReference => ARef}
class MyAtomicReference[V] extends ARef[V]{
private val getCounter: AInt = new AInt(0)
def getAndListen(): V = {
getCounter.getAndIncrement()
super.get()
}
def counter(): Int = getCounter.get()
def resetCounter(): Unit = getCounter.set(0)
}
Then I've added trait AtomicRefCounter which declares the method that I would wish to invoke:
import simulacrum.typeclass
#typeclass trait AtomicRefCounter [R[_], T] {
def countGets(container: R[T]): Int
}
Lastly, I've defined a default AtomicArrayRefCounter in the object DefaultAtomicRefCounters:
object DefaultAtomicRefCounters {
implicit val arrayOfAtomicsTraverser = new AtomicRefCounter[Array, MyAtomicReference[_]] {
override def countGets(container: Array[MyAtomicReference[_]]): Int = container map(_.counter()) sum
}
}
Despite that when I try to call the traverseAtomics() on a corresponding array in a test, I do not see it (I am using Intellij IDEA):
behavior of "removeO1"
"method" should "remove an element from the pool with time O(1)" in new IntPoolBuilder {
import org.learningconcurrency.traditional_concurrency.helpers.DefaultAtomicRefCounters._
pool.buckets.countGet
}
A piece of advice on what I am missing would really help. Usage of simulacrum is not mandatory - if you feel you know how to solve this without it, I would love to hear that.
update:
This is how the buckets are implemented:
class Pool[T] {
type TimeStampedList = (List[T], Long)
val parallelism: Int = Runtime.getRuntime.availableProcessors * 32
val buckets = new Array[MyAtomicReference[TimeStampedList]](parallelism)
...
I think, you might have gotten wrong how implicits work.
If I read everything correctly, then in your code
implicitly[AtomicRefCounter[Array, MyAtomicReference[_]]].countGets(pool.buckets)
should work.
I you wanted to call countGets on the Array you should use the EnrichMyLibrary pattern.
object DefaultAtomicRefCounters {
implicit class RichArray(private underlying: Array[MyAtomicReference[_]] extends AnyVal {
def countGets: Int = underlying.map(_.counter()).sum
}
}
As disappointing as it is, I couldn't make it work with simulacrum annotation, so I've followed Sascha's advise. I just modified slightly his second example (I couldn't get it to work with implictly) so it compiles and works:
object TraditionalConcurrencyHelpers {
implicit class CountArrayAtomicGetsOps(wrapper: Array[MyAtomicReference[(List[Int], Long)]]) {
def countGets()(implicit atomicRefCounter: AtomicRefCounter[Array, MyAtomicReference[(List[Int], Long)]]): Int = atomicRefCounter.countGets(wrapper)
}
}
With this I have no problem calling countGets on the array:
behavior of "removeO1"
"method" should "remove an element from the pool with time O(1)" in new IntPoolBuilder {
import TraditionalConcurrencyHelpers._
import org.learningconcurrency.traditional_concurrency.helpers.DefaultAtomicRefCounters._
//call pool.removeO1 (not implemented yet)
pool.buckets.countGets() shouldEqual 1
}

Scala class - required property

I would like to define trait that has const property, for example:
trait InitialTest {
// property would be set here or somewhere else, let's call it typeNumber
override def toString = typeNumber.toString
}
then I would like to set this value for each implementation like:
case class InitialTest1 extends InitialTest {
// set value here like typeNumber = 4
}
For each toString function would use impelemetation from trait.
Do you know how can I acheive it?
The easiest way of achieving it, that I see is:
trait MyTrait {
val myProperty: X // abstract property
override def toString: String = myProperty.toString
}
It would force implementation of the property:
class Impl extends MyTrait {
val myProperty = new X // without that line it doesn't compile
}
From there on, one might complicate design further e.g. by splitting the trait with the property from the trait overriding toString with a cake pattern (though I'd be vary about it).

what is the best practice of implementing a factory pattern/method in scala?

I wonder what is the best practice of implementing a factory pattern/method in scala?
say we have those kind of objects:
case class foo1(a:Int,b:String)
case class goo1(z:Double, w:String)
how to create them in generic way [by maybe using a trait etc...]?
thanks
If your goal is to write your own dependency injection module that provides instances on the fly, I'd strongly suggest that you lookup some of the existing tools. A simple google search for "Scala dependency injection frameworks" will yield many result such as MacWire, Guice,ReaderMonad,cake pattern and etc.
However my judgement aside from your motive and to simply answer the question here's one way you would do this in scala that also is type safe:
trait FactoryMethod[T] {
type Args
def defaultArgs: Args
def withArgs(args: Args): T
def default: T = withArgs(defaultArgs)
}
case class Foo(a:Int,b:String)
object Foo {
implicit object factory extends FactoryMethod[Foo] {
override type Args = (Int,String)
override def withArgs(args: Args): Foo = (Foo.apply _).tupled(args)
override def defaultArgs: Args = (1,"foo")
}
}
case class Goo(z:Double, w:String)
object Goo {
implicit object factory extends FactoryMethod[Goo] {
override type Args = (Double,String)
override def withArgs(args: Args): Goo = (Goo.apply _).tupled(args)
override def defaultArgs: Args = (2L,"goo")
}
}
object Factory {
def of[T](implicit factory: FactoryMethod[T]): factory.Args => T = factory.withArgs
def instanceOf[T](implicit factory: FactoryMethod[T]): T = factory.default
}
//obtain instance with default arguments
Factory.instanceOf[Goo]
//type safe way of obtaining instance with custom fed arguments
Factory.of[Foo].apply((-22,"baz"))
//By type safe I mean that the line below won't compile because the
//arguments fed for Foo are not compatible:
//Factory.of[Foo].apply(("bar","baz"))
//Note that if you abstract over the types Goo and Foo like this:
//def myMethod[T]: T = {
// Factory.instanceOf[T]
//}
//It won't compile unless you also ask for the needed implicit
//on the method signature
def myMethod[T: FactoryMethod]: T = {
Factory.instanceOf[T]
}

Scala: reconfigure trait using CLI parameters

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()

Why can't I access my objects member variable?

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.