Scala: Extend base class that contains 'apply' method - scala

I have a base class in the 'common' module that looks like this:
class BaseClass(args: Seq[String] = Seq()) extends Serializable {
private val argMap: Map[String, String] =
// <More code here...>
object BaseClass {
def apply(args: Seq[String] = Seq()): BaseClass = new BaseClass(args)
}
Now I want to extend this BaseClass in my 'module' so I am trying this...
class MyNewClass(args: Seq[String] = Seq()) extends com.xyz.BaseClass {
// Add additional code here
}
object MyNewClass extends com.xyz.BaseClass {
def apply(args: Seq[String] = Seq()): MyNewClass = new com.xyz.MyNewClass(args)
}
My understanding is, when I instantiate MyNewClass it will automatically instantiate & call the 'apply' method of the base class but that's not happening. What is a proper way to extend the BaseClass in a way that all its variables & methods can be accessed via the Child class?

My understanding is, when I instantiate MyNewClass it will automatically instantiate & call the 'apply' method of the base class...
Your understanding isn't quite on.
extends com.xyz.BaseClass means that this class inherits from the base class, not the singleton object.
And new com.xyz.MyNewClass(args) creates a new instance of the specified class, bypassing the apply() method in any companion object.
What is a proper way to extend the BaseClass in a way that all its variables & methods can be accessed via the Child class?
The current code does exactly that. MyNewClass, and its companion object, inherits all members from BaseClass. Nothing is inherited from the BaseClass companion object because you can't extend an object, and you don't inherit the access permissions from BasseClass so while a BaseClass instance can access private members of the BaseClass companion object, a MyNewClass instance cannot.

Related

Scala companion objects are not singleton

I have following two classes.
class A (name: String) {
}
object A {
}
According to definition of Singleton, we can have only one object of that type. However I am able to create two different objects of type A using following piece of code.
object B {
def main(args: Array[String]): Unit = {
val a = new A("Vinod")
println(a)
val b = new A("XYZ")
println(b)
}
}
can someone please explain me, where my understanding is not correct?
An object by itself is a singleton. It has its own class and no other instance of the same class exist at runtime.
However, the pattern you describe here is different: object A is not an instance of class A unless you make it so using object A extends A. You could make it the only instance of class A by making class A a sealed class, but this is unnecessary in almost all cases.
If you really want the singleton pattern, drop the class and use only object A, all of its members will be "static" in the sense of Java.
Note that the actual type of object A can be referred to as A.type, which by default is completely unrelated to type A if class A exists. Again, A.type could be a subtype of A if you explicitly make it so.
The companion object is not an instance of the companion class. They're not even the same type.
class A
object A {
var state = 0
def update() :Unit = state = state + 1
}
val abc :A = new A //instance of class A
val xyz :A.type = A //2nd reference to object A
// both reference the same singleton object
xyz.update() //res0: Unit = ()
A.state //res1: Int = 1
abc.state //Error: value state is not a member of A$A2521.this.A
the companion object can be thought of as the static space of a class. if you want to make A a singleton you can make it an object rather than a class
new A refers to class A (which is not a singleton), not to object A. You can easily check it: if you remove class A, the new A lines will no longer compile.
Also note that objects aren't necessarily singletons: they can be nested inside classes or traits, in this case there is one for each instance of the outer type.

Make constructor parameters public in subclass

I want the protected fields of a class to be made publicly visible in a subclass:
class MyClass(protected val someDao: SomeDao)
class TestMyClass extends MyClass(mock[SomeDao])
Now I want to access someDao like so:
val testClass = new TestMyClass
testClass.someDao
I've read that in Java and Scala access modifiers can be broadened but not restricted in subclasses (although these are just constructor parameters, not private fields per se). How can I achieve that in this example?
EDIT:
The answers provided suggest making someDao public in the base class. This is not what I want. I want it to remain private, but just change its visibility to public in the TestMyClass class.
As far as I know, an overriden val cannot access the super implementation.
If you can modify the base class, one solution is to explicitely define an accessor method, which can be overriden; something like this:
class MyClass(_someDao: SomeDao) {
protected def someDao = _someDao
}
class TestMyClass extends MyClass(mock[SomeDao]) {
override def someDao = super.someDao
}
If you cannot change the base class, one workaround would be to define a public accessor method with a different name:
class MyClass(protected val someDao: SomeDao)
class TestMyClass extends MyClass(mock[SomeDao]) {
def someDao2 = someDao
}
Add var or val to parameters declaration:
class MyClass(val someDao: SomeDao)
In this case only getter function will be generate for someDao field. So when you write testClass.someDao you retrieve not the someDao as field you use their getter function.
Good example about visibility of class parameters in Scala demostrated at this article.
Regarding to your last updates
Set package scope for parameter declaration:
class MyClass(private[lastPackageOfSomeDao] val someDao: SomeDao)

Writing a Python method to reference the Class attribute in the derived class, rather than base class

As someone who worked more in Java, I am having a bit of difficulty wrapping my head around polymorphic references to class attributes in Python.
What I would like to do is have a method in the base class which modifies a "static" variable (aka class attribute) of the base class, but when calling the method from the derived class, for the method to modify the class attribute of the derived class, not the base class. Note, I am NOT overriding the method in the derived class.
For example, I have something like:
class BaseClass:
itemList = []
def addItem(thing):
BaseClass.itemList.append(thing)
class Child1(BaseClass):
pass
class Child2(BaseClass):
pass
...
Child1.addItem("foo")
Child2.addItem("bar")
print(str(Child1.itemList))
I'd like: "foo"
I get: "foo, bar"
Now, I understand that because of "BaseClass.itemList.append(thing)", it will reference the class attribute of the base class.
Put another way, is there a way to avoid saying "BaseClass.itemList", but keep it static, or do I need to instead override the method in each of the child classes?
You can have a "static" class variable that can be changed by every instance of the class:
class BaseClass:
itemList = []
def addItem(self, thing):
self.itemList.append(thing)
class Child1(BaseClass):
itemList = []
class Child2(BaseClass):
itemList = []
# each class has its own "itemList"
# now we can instantiate each class and use the different itemLists:
c1 = Child1()
c1.addItem("foo")
c2 = Child2()
c2.addItem("bar")
c3 = Child1()
c3.addItem("foo2")
print(str(Child1.itemList)) # prints: ['foo', 'foo2']
print(str(Child2.itemList)) # prints: ['bar']

Can't access method of companion class from companion object

I thought that I can access every method of the companion class from my companion object. But I can't?
class EFCriteriaType(tag:String) extends CriteriaType
{
// implemented method of CriteriaType
def getTag = this.tag
}
object EFCriteriaType
{
var TEXT: CriteriaType = new EFCriteriaType("text")
override def toString = getTag
}
Compiler error:
not found: value getTag
What I'm doing wrong?
You are trying to call the method getTag in object EFCriteriaType. There is no such method in that object. You could do something like:
object EFCriteriaType extends EFCriteriaType("text") {
override def toString = getTag
}
Thus making the companion object a kind of template.
You can access members not normally accessible in a class from a companion object, but you still need to have an instance of the class to access them. E.g:
class Foo {
private def secret = "secret"
def visible = "visible"
}
object Foo {
def printSecret(f:Foo) = println(f.secret) // This compiles
}
object Bar {
def printSecret(f:Foo) = println(f.secret) // This does not compile
}
Here the private method secret is accessible from Foo's companion object. Bar will not compile since secret is inaccessible.
I'm not quite sure what you're trying to do here, but you need to call getTag on an instance of the class:
override def toString(x:EFCriteriaType) = x.getTag
Just to detail Matthew answer, which is the right one:
A companion object is a singleton but a class is not. a singleton. The companion
object can access the methods of the class in the sense that a private
member of the class C can be called in its companion object C.
To call a member of a given class, you need an instance of that class (even if you are not doing that from a companion object)
follow this example, please:
import scala.math._
case class Circle(radius: Double) {
import Circle._
def area: Double = calculateArea(radius)
}
object Circle {
private def calculateArea(radius: Double): Double = Pi * pow(radius, 2.0)
}
val circle1 = Circle(5.0)
circle1.area

Using Scala companion object as factory by extending a factory trait. Better solution?

Scala companion objects are frequently proposed as object factories. They seem to work well for this in the production code, but what about inserting mock objects for testing? The companion object won't know about the mock object and therefore cannot instantiate it.
I'd like to do something like this:
class Foo {}
object Foo {
def create():Foo = new Foo()
}
class FooCreator(factory:Foo) {
def this() = this(Foo)
...
factory.create()
...
}
class FooMock extends Foo {}
object FooMock extends Foo {
def create():Foo = new FooMock()
}
// in a test
val fooCreator = new FooCreator(FooMock)
This won't work because a companion object cannot be extended. I'm forced to create a Factory trait for both companion objects to mixin:
trait FooFactory {
def create():Foo;
}
class Foo {}
object Foo extends FooFactory {
def create():Foo = new Foo()
}
class FooCreator(factory:FooFactory) {
def this() = this(Foo)
...
factory.create()
...
}
class FooMock extends Foo {}
object FooMock extends FooFactory {
def create():Foo = new FooMock()
}
// in a test
val fooCreator = new FooCreator(FooMock)
Is there a better way to do this? Creating the factory trait just feels wrong, since that's what the companion object is supposed to be good at. (Keep in mind that the Mock artifacts are only known to the test subsystem, so I can't solve the problem by letting object Foo create a FooMock instance - the common pattern in production code).
Use the apply method rather than the object as your factory, as detailed in the answers to my question How to use companion factory objects as strategy?
You might want to take a look at ScalaMock, a mocking framework for Scala that can (among other things) mock object creation (compiler invocation). This is exactly one of the problems it's intended to solve.