Trouble with overriding a variable in abstract class - scala

I'm new to scala and have the following question about overriding a variable in an abstract class.
abstract class ExampleClass1 {
val testVar = (i: String) => {
i + " A"
}
def exampleMethod1() = {
print testVar
}
}
object ExampleObject1 extends ExampleClass1 {
def getExampleValue() = {
exampleMethod1()
}
}
ExampleClass1 and ExampleObject1 are in one module. My module is calling ExampleObject1.getExampleValue. I want to change the behavior of testVar in ExampleClass1. Is it possible to do this without changing ExampleObjectt1?
Thank you

If you want to change a value after the class is instantiated, then you should use var instead of val, but without any further information it seems that there is a flaw in your design.
If you want to set the value of the given string on object creation, you can use something like this:
scala> abstract class ExampleClass1(val i: String)
defined class ExampleClass1
scala> object ExampleObject1 extends ExampleClass1("A")
defined object ExampleObject1
scala> ExampleObject1.i
res1: String = A
Or if you want to use given string as a parameter:
scala> abstract class ExampleClass2 {
| def test(i: String) = i + " A"
| }
defined class ExampleClass2
scala> object ExampleObject2 extends ExampleClass2
defined object ExampleObject2
scala> ExampleObject2.test("B")
res2: String = B A
What is your goal?

Related

Scala - object extends abstract class and takes parameters

//File Animal.scala
abstract class Animal {
val name: String
def getSomething(tClass: TypeClass): String = {
tClass.tName.split('.').lift(0)
}
def apply(tClass: TypeClass): SomeOtherClassType = {
// something...
}
// File: DogSpike, this is used for some specific cases (overwrites
base class val)
object DogSpike extends Animal {
override val name: String = "Spike"
}
this call then works (calls apply)
myTransformation(() => DogSpike(this))
Now I would like to create a more generic object that one can pass arguments but I am unable to.
It would work to create a derived Object from Animal that takes one arguments and being able to use the apply call
object TheDog(name: String) extends Animal {
override val name: String = "Spike"
//...
}
not sure how to implicitly call Animal.apply for TheDog object where I could pass a parameter (name)
myTransformation(() => TheDog(this))
// also this seems to be incorrect "*Wrong top statement declaration*"
object TheDog(val n: String) extends Animal {
override val name: String = n
//...
}
As of *Wrong top statement declaration* (I can understand only this part of your question) - you can't have constructor in object as object is a singleton, so you should use a case class (ADT):
final case class TheDog(name: String) extends Animal
scala>TheDog("Spike")
res2_2: TheDog = TheDog("Spike")
val and companion object with apply is added automatically for case classes, so you don't need to define your own own apply in Animal. case class TheDog(val name: String) is same as case class TheDog(name: String).
I's also use traits instead of abstract class:
trait Animal {
val name: String
def getSomething: String = {
"Dog: " + name
}
}
I don't understand your TypeClass type, but if you really want type classes:
trait Animal {
def name: String
}
final case class TheDog(name: String) extends Animal
final case class TheCat(name: String) extends Animal
implicit class RichDog(dog: TheDog){
def getSomething: String = {
"Dog" + dog.name
}
}
implicit class RichCat(cat: TheCat){
def getSomething: String = {
"Cat: " + cat.name
}
}
scala> TheDog("Spike").getSomething
res4_5: String = "DogSpike"
scala> TheCat("Tom").getSomething
res4_6: String = "Cat: Tom"
About calling apply "implicitly", I don't know why would anyone need this, but:
trait AnimalFactory[A <: Animal] {
def apply(name: String)(implicit constructor: String => A) = constructor(name)
}
object TheeeDog extends AnimalFactory[TheDog]
implicit def createDog(name: String) = TheDog(name)
TheeeDog("Spike")
Of course you have to provide createDog and make it visible for a client, but it doesn't really make sense if you can just use ADTs and define additional required applys in companion object:
case class TheMouse(name: String)
object TheMouse{
def apply(isJerry: Boolean): TheMouse = if (isJerry) TheMouse("Jerry") else TheMouse("NotJerry")
}
TheMouse(true)
If you want to add some parameter to constructor, just add it:
class AnimalFactory(clazz: SomeClass){
def doSomething = clazz.name
def apply(name: String)
}
val dogFactory = new AnimalFactory(dogClassDescriptor)
val catFactory = new AnimalFactory(catClassDescriptor)
dogFactory("Spike")
catFactory("Tom")
You can even create a factory for factory (I wouldn't recommend - this solution already looks overcomplicated):
object AnimalFactory{ //please don't use classes for that - avoiding `new` is not their purpose
def apply(clazz: SomeClass) = new AnimalFactory(clazz)
}
val dogFactory = AnimalFactory(dogClassDescriptor)
//or even `val spike = AnimalFactory(dogClassDescriptor)("Spike")`
But still what's the point if you could just provide underlying clazz either as a member or just in a wrapper:
final case class ClazzWrapper[T <: Animal](clazz: SomeClass, animal: T)

Overriding vals in Scala

I have tried to override val in Scala as this:
trait T{
val str: String
}
sealed abstract class Test extends T{
val str: String = "str"
}
class Test1 extends Test{
val str = super.str + "test1" //super may not be used on value str
}
But this refused to compile. Why? I wanted to override value in the abstract class using the abstract class's value itself. How to do this?
In my particular case I cannot pass it as a class parameter.
Scala compiler does not allow to use super on a val. If you are not caring about re-evaluation, you can just use def instead.
trait T{
def str: String
}
sealed abstract class Test extends T{
def str: String = "str"
}
class Test1 extends Test{
def str = super.str + "test1" //super may not be used on value str
}
defined trait T
defined class Test
defined class Test1
If you do care about it avoiding repeated initialization, you can extract it into a method:
sealed abstract class Test extends T {
lazy val str: String = initStr
protected def initStr = "str"
}
class Test1 extends Test{
override protected def initStr = super.initStr + "test1"
}
You can also make str non-lazy, but it's all to easy to end up with initialization order problems that way.

Use method to override itself in scala

Is there a way in scala to use a method m in the implementation of the method overriding the same method m?
As an example here is what I tried (note that toUpperCase is not implemented):
abstract class Person {
def greet: String
}
class EnglishMan extends Person {
abstract override def greet: String =
{
return "hello"
}
}
trait Angry extends Person {
abstract override def greet: String =
{
return toUpperCase(greet)
}
Is this what you want?
scala> trait Person { def greet: String }
defined trait Person
scala> class EnglishMan extends Person { def greet = "hello" }
defined class EnglishMan
scala> class Angry extends EnglishMan { override def greet = super.greet.toUpperCase }
defined class Angry
scala>
scala> new EnglishMan().greet
res3: String = hello
scala> new Angry().greet
res4: String = HELLO
Note that trait Person is completely irrelevant to this exercise. You can invoke your superclass' methods (even when overriding that very method), but you can't have 2 methods on the same scope with the same name (that would be ambiguous for the compiler).

Scala - Making sure that a field from the superclass is used

In Scala, fields are declared in the primary constructor. And, if it happens to have the same name as a field from the super class, it will use the one passed in instead, which is what I am trying to avoid. Take the following example:
class Parent(protected val changedParam: MyClass)
class Child(changedParam: MyClass) extends Parent(doStuff(changedParam)) {
def foo() = {
bar(changedParam) // Uses Child.changedParam, not Parent.changedParam, which is what I want
}
}
I want to make changedParam in Child to refer to the changedParam in Parent, not Child. Is there any way to do that?
A parameter of a class is visible in its body. It will be made a private val if need be, that is if it is used in a method, and not just in the initialization code (and of course if it is not directly declared a val with a different visibility, or a var).
So changedParam in Child shadows the one in Base. The obvious way to avoid that is simply to call it another name:
class Child(anotherName: MyClass) extends Base(doStuff(anotherName)) {...
This is considered brittle and annoying.
You get a little relief if you're shadowing a var:
scala> class A { var a = 1 } ; class B(a: Int) extends A { def f = a }
defined class A
defined class B
scala> val b = new B(42) ; b.a = 7 ; b.f
b: B = B#1376c05c
b.a: Int = 7
res0: Int = 42
scala> :replay -Xlint
Replaying: class A { var a = 1 } ; class B(a: Int) extends A { def f = a }
<console>:7: warning: private[this] value a in class B shadows mutable a inherited from class A. Changes to a will not be visible within class B - you may want to give them distinct names.
class A { var a = 1 } ; class B(a: Int) extends A { def f = a }
^
defined class A
defined class B
Replaying: val b = new B(42) ; b.a = 7 ; b.f
b: B = B#f2ff811
b.a: Int = 7
res0: Int = 42
Normally, shadowing a val is more benign, but a warning for your example would be useful.
class Parent(protected val changedParam: MyClass)
trait Child extends Parent {
def foo() = {
bar(changedParam)
}
}
object Child {
def apply(changedParam: MyClass): Child =
new Parent(doStuff(changedParam)) with Child
}
Not much to say... Turning Child into a trait avoids to declare a new temporary member that you don't want to be used after the initialization. Then I used the companion object to declare the constructor. The only difference in usage is that you don't have to add the new keyword to instanciate Child.
Test:
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Parent(protected val changedParam: Int)
trait Child extends Parent {
def foo() = {
println(changedParam)
}
}
object Child {
def apply(changedParam: Int): Child =
new Parent(1 + changedParam) with Child
}
// Exiting paste mode, now interpreting.
defined class Parent
defined trait Child
defined object Child
scala> Child(42).foo()
43
1) Using explicit call to Parent with asInstanceOf:
package demo {
// remove protected or make it protected[demo]
class Parent(protected[demo] val changedParam: MyClass)
class Child(changedParam: MyClass)
extends Parent(doStuff(changedParam)) {
def foo() = {
bar(this.asInstanceOf[Parent].changedParam)
}
}
}
2) Using early initializers syntax:
class Parent(protected val changedParam: MyClass)
class Child(changedParam: MyClass) extends {
val superChangedParam = doStuff(changedParam)
} with Parent(superChangedParam) {
def foo() = {
bar(superChangedParam)
}
}
Nevertheless the best solution is to give a different name to your param.

Scala: How can I implement a clone method on a superclass, and use it in a subclass?

I might be approaching this the wrong way, but I'd like to have an object like this:
class MyDataStructure {
def myClone = {
val clone = new MyDataStructure
// do stuff to make clone the same as this
...
clone
}
}
class MyDataStructureExtended(val foo: String) extends MyDataStructure
Then:
val data = MyDataStructureExtended
val dataClone = data.clone
println(dataClone.foo)
So, the problem is that dataClone is of type MyDataStructure, not MyDataStructureExtended as I'd hoped.
I thought about adding a type T to the super class, that the subclass can specify (e.g. itself), but that didn't seem very promising.
As you have suggested, abstract types, or generic parameters, are what you need. Do you require that MyDataStructure not be a trait or abstract class? The following defines MyDataStructure to be an abstract class, but you can make it a trait as well.
abstract class MyDataStructure {
type T
def myClone: T
}
class MyDataStructureExtended(foo: String) extends MyDataStructure {
type T = MyDataStructureExtended
def myClone = new MyDataStructureExtended(foo)
}
The results from the Scala interpreter show that the myClone method defined in MyDataStructureExtended is the correct type.
scala> val mde = new MyDataStructureExtended("foo")
val mde = new MyDataStructureExtended("foo")
mde: MyDataStructureExtended = MyDataStructureExtended#3ff5d699
scala> val cloned = mde.myClone
val cloned = mde.myClone
cloned: MyDataStructureExtended = MyDataStructureExtended#2e1ed620
You might want to restrict T so that its type can only be that of MyDataStructure subclasses
abstract class MyDataStructure {
type T <: MyDataStructure
def myClone: T
}
I don't know your requirements, but I believe that Scala 2.8 will have some nice functionality with case classes and named arguments that allow one to clone case classes with a copy method.
Assuming you want to minimize amount of ceremony in the subclasses, here is my suggestion:
class A extends Cloneable {
protected[this] def myCloneImpl[T] = {
val justLikeMe = this.clone
// copy values and such.
// Note that the Object.clone method already made a shallow copy, but you may want
// to deepen the copy or do other operations.
justLikeMe.asInstanceOf[T]
}
def myClone = myCloneImpl[A]
}
class B extends A {
override def myClone = myCloneImpl[B]
}
By extending java.lang.Cloneable and calling the Object.clone method, you ensure that your runtime type is the same as the object being cloned. The static type is coerced with a type-cast (asInstanceOf[T]). You will need to override the myClone method in each subclass and specify the type, but it should be a one-liner.
Hard to say whether you're doing it right with such a vague problem description, but it's actually pretty straightforward to do this. You can simply override myclone in MyDataStructureExtended such that it returns the more specific type. When you have a variable of the more specific type, you'll be able to use the more specific clone method as well.
Example code in case that description was unclear:
class A {
def getMe = this
}
class B extends A {
override def getMe = this
def isAnInstanceOfB = true
}
And a corresponding REPL session:
scala> val a = new A
a: A = A#1a6eeab
scala> val b = new B
b: B = B#a36771
scala> a.getMe
res0: A = A#1a6eeab
scala> a.getMe.isAnInstanceOfB
<console>:7: error: value isAnInstanceOfB is not a member of A
a.getMe.isAnInstanceOfB
^
scala> b.isAnInstanceOfB
res2: Boolean = true
scala> b.getMe.isAnInstanceOfB
res3: Boolean = true
I think this could be the solution. This is not inherited and you can do some modification to achieve your thing. Good Luck.
class CloneableClass extends scala.Cloneable {
def myMethod: Unit = println("Inside "+this.getClass)
override def clone(): CloneableClass =super.clone().asInstanceOf[this.type]
}
class CloneableDemo {
val cc = new CloneableClass
val cc1 = cc.clone()
cc1.myMethod
}
object CloneObject extends App {
val cd = new CloneableDemo
}