Val and Overrides in Scala - scala

As i understand vals are immutable in Scala. However in case of inheritance we can override a val defined in the base class. If the val member already got created when the base class was constructed then how can derived class override it? What am i missing?
class Animal ()
{
val talk: String = "Ha Ha!"
}
class Dog extends Animal
{
override val talk = "Woof Woof!"
}
class Cat extends Animal
#main def mainFn() = {
var happyAnimal = new Animal()
println(happyAnimal.talk)
happyAnimal = new Dog()
println(happyAnimal.talk)
happyAnimal = new Cat()
println(happyAnimal.talk)
}
Output
Ha Ha!
Woof Woof!
Ha Ha!

Related

How do I pass an inherited variable into a Auxiliary constructor from a trait

I'm looking to get the value bork and pass it to a class into the class in the constuctor.
trait dog {
lazy val bork = "bork"
}
class Animal(val firstName: String, dogCommand: DogCommand) extends dog{
def this(firstName: String) {
this(firstName, DogCommand(bork))
}
def getDogCommand(): Unit = {
dogCommand.getCommand()
}
}
case class DogCommand(command: String) {
def getCommand() :Unit = {
println(command)
}
}
val myDog = new Animal("first")
myDog.getDogCommand()
I usually get - error: not found: value bork
The problem is that bork is a value on dog but there is no instance of dog available to read the bork from. this is a constructor so it doesn't have access to the value that is being constructed.
This is one solution that retains most of the original code:
trait dog {
def bork = dog.DefaultBork
}
object dog {
val DefaultBork = "bork"
}
class Animal(val firstName: String, dogCommand: DogCommand) extends dog {
def this(firstName: String) = this(firstName, DogCommand(dog.DefaultBork))
...
}
You could consider removing the default value of bork in dog so that any class implementing the trait is required to provide a value for bork. (It can always use DefaultBork if it wants to retain the default value)
For one item, your this constructor is incorrect. I also renamed Dog. As for your lazy val that wouldn't work on a trait. See more here why scala don't allow define lazy val in trait?. Even if you make it non-lazy, that value is not initialized yet until construction when that val is not available, yet. Another problem would also be logic, an Animal is not Dog, but the other way around. Here is an alternative: https://scastie.scala-lang.org/WnhxzSn6QtOf5vo1epDDqQ Hope that helps. ;)
trait Dog {
lazy val bork = "bork"
}
class Animal(val firstName: String, dogCommand: DogCommand) extends Dog {
def this(firstName: String) = this(firstName, DogCommand(bork))
def getDogCommand(): Unit = {
dogCommand.getCommand()
}
}
case class DogCommand(command: String) {
def getCommand() :Unit = {
println(command)
}
}
val myDog = new Animal("first")
myDog.getDogCommand()

Companion Object override few methods of a trait

So. Assume we have a trait Animal
trait Animal {
val typeAnimal: String
val name: String
}
And now I want to create a class Dog, that extends this trait. But I want to use the Companion Object to override the typeAnimal to Mammal, instead to do it on the class Dog itself.
Something like
class Dog(override val name: String) extends Animal
object Dog {
override val typeAnimal = "Mammal"
}
This doesn't work. It raises an error saying to me:
class Dog doesn't implement typeAnimal
the override of typeAnimal on the companion object does not override anything
Is it even possible?
Does it have make sense what I'm trying to achieve?
EDIT
I assume it's not possible to achieve what I'm trying here following Jorg's comment.
What I was trying to do is: a trait define some static value that each class should implement, like typeAnimal, and, since this belongs to all the instance of each class that implements this trait (e.g. Dog is a mammal, so I don't see any reason why the typeAnimal should be a instance variable instead of a static one) I would like to override in the companion object
If you want typeAnimal to be "static", it shouldn't be a member of the trait itself. You can do this instead:
trait Animal {
val name: String
def companion: AnimalCompanion
// optional: def typeAnimal = companion.typeAnimal
}
trait AnimalCompanion {
val typeAnimal: String
}
class Dog(override val name: String) extends Animal {
override def companion = Dog
}
object Dog extends AnimalCompanion {
override val typeAnimal = "Mammal"
}
The standard library does that with collections.

Stub a val of a trait with scalamock

In the following (simplified) example, how can I stub the value of a trait that inherits fields from a class with scalamock?
trait MyTrait extends MyClass
class MyClass(val location: Location)
val expectedValue = ???
val dor: MyTrait = stub[MyTrait]
(dor.location.continuousFeatureValues).returns(expectedValue)
'location' is the parameter of MyClass or a data member of MyClass? Is it OK to change MyClass as:
class MyClass() {
val location: Location = new Location
}
If it is OK, you can override the location as a workaround:
//source code
class Location {
def continuousFeatureValues: String = "location"
}
class MyClass() {
val location: Location = new Location
}
class MyTrait extends MyClass
// test code
it should "mock" in {
val loc = mock[Location]
val dor: MyTrait = new MyTrait {override val location = loc}
(loc.continuousFeatureValues _).expects().returning("good")
dor.location.continuousFeatureValues shouldBe ("good")
}
I would refactor that code, as it is a bit of a dead end with a trait extending a class with a non-default constructor.
If you were to mock that class directly, you still could not define actions on location as it is a val, and those are immutable in Scala. Make it a def on MyTrait and have MyClass extend MyTrait and your design should be simpler to work with (and mock).

Scala Generics with Case Class and Object Companion

I have this:
case class Aaa() extends NClass {
def method1() = println("method1")
}
object Aaa extends NCompanion {
def method2() = println("method2")
}
I would like to implement something like the following pseudo code:
abstract class Xxx[T] {
// All the trash code of reflection/implicit should be in this class only
instance = new T()
companion = T
instance.method1()
companion.method2()
}
To use like this:
class Yyy extends Xxx[Aaa] {}
How can I implement this? It is better if I could use the new Scala Reflection API. Thanks in advance!
For now I am using a solution avoiding get the companion type with generics:
abstract class Xxx[T <: NClass[T], O <: NCompanion[T]](implicit tag: TypeTag[T]) {
def getInstance(): T
def getCompanion(): O
val classOfT = typeTag[T].mirror.runtimeClass(typeOf[T])
val className = classOfT.getName
println(s"$className")
val t = getInstance()
val manager = getCompanion()
}
Usage:
class Yyy extends Xxx[Aaa, Aaa.type] {
override def getInstance: Aaa = {
return new Aaa()
}
override def getCompanion: Aaa.type = {
return Aaa
}
}

Avoiding NPE in trait initialization without using lazy vals

This is probably covered by the blog entry by Jesse Eichar—still I can't figure out how to correct the following without resorting to lazy vals so that the NPE is fixed:
Given
trait FooLike { def foo: String }
case class Foo(foo: String) extends FooLike
trait Sys {
type D <: FooLike
def bar: D
}
trait Confluent extends Sys {
type D = Foo
}
trait Mixin extends Sys {
val global = bar.foo
}
First attempt:
class System1 extends Mixin with Confluent {
val bar = Foo("npe")
}
new System1 // boom!!
Second attempt, changing mixin order
class System2 extends Confluent with Mixin {
val bar = Foo("npe")
}
new System2 // boom!!
Now I use both bar and global very heavily, and therefore I don't want to pay a lazy-val tax just because Scala (2.9.2) doesn't get the initialisation right. What to do?
You can use an early initializer:
class System1 extends {
val bar = Foo("npe")
} with Mixin with Confluent {
// ...
}
scala> new System1
res3: System1 = System1#1d0bfedd