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
Related
I have a superclass:
class Filter(val param: ComplexFilterParams){
def this(config: String) = this(parseStrConfig(config))
And I need to create a subclass that gets a String argument and then parses it in another way and creates ComplexFilterParams.
Something like that:
class NewFilter(str:String) extends Filter {
Is there a way to do it?
I got one solution. But I think it's ugly. I create companion object, define there a convert method and do next:
class NewFilter(str:String) extends Filter(NewFilter.convert(str)) {
You can go mush easier with another apply implementation in companion object like:
class NewFilter(val param: ComplexFilterParams) extends Filter(param){
//other implementations
}
object NewFilter {
def apply(str: String) = new NewFilter(convert(str))
def convert(str: String): ComplexFilterParams = ...
}
val filter = NewFilter("config string")
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.
In Scala, a class and an object can be companion(same name, same file)
I came across Scala source code, with a file having a trait and object defined in it and both having same name, but object is not extending trait.
Is this style ok?
Yes, In both the case trait or object same name object become a companion object you can see below code you can access private members in class and trait both situations
trait
trait Simple {
private def line = "Line"
}
object Simple {
val objTrait = new Simple{}
def lineObj=objTrait.line
}
Simple.lineObj
class
class Simple {
private def line = "Line"
}
object Simple {
val objTrait = new Simple{}
def lineObj=objTrait.line
}
Simple.lineObj
A typical use case for object is for methods and fields that you would mark as static in Java, if that helps.
The object doesn't extend the trait / class, it accompanies it, hence the term companion object.
I want to do something like this:
interface Serializable<FromType, ToType> {
fun serialize(): ToType
companion object {
abstract fun deserialize(serialized: ToType): FromType
}
}
or even this would work for me:
interface Serializable<ToType> {
fun serialize(): ToType
constructor(serialized: ToType)
}
but neither compiles. Is there a syntax for this, or will I be forced to use make this an interface for a factory? Or is there another answer? 😮 That'd be neat!
Basically, nothing in a companion object can be abstract or open (and thus be overridden), and there's no way to require the implementations' companion objects to have a method or to define/require a constructor in an interface.
A possible solution for you is to separate these two functions into two interfaces:
interface Serializable<ToType> {
fun serialize(): ToType
}
interface Deserializer<FromType, ToType> {
fun deserialize(serialized: ToType): FromType
}
This way, you will be able to implement the first interface in a class and make its companion object implement the other one:
class C: Serializable<String> {
override fun serialize(): String = "..."
companion object : Deserializer<C, String> {
override fun deserialize(serialized: String): C = C()
}
}
Also, there's a severe limitation that only a single generic specialization of a type can be used as a supertype, so this model of serializing through the interface implementation may turn out not scalable enough, not allowing multiple implementations with different ToTypes.
For future uses, it's also possible to give the child class to a function as a receiver parameter:
val encodableClass = EncodableClass("Some Value")
//The encode function is accessed like a member function on an instance
val stringRepresentation = encodableClass.encode()
//The decode function is accessed statically
val decodedClass = EncodableClass.decode(stringRepresentation)
interface Encodable<T> {
fun T.encode(): String
fun decode(stringRepresentation: String): T
}
class EncodableClass(private val someValue: String) {
// This is the remaining awkwardness,
// you have to give the containing class as a Type Parameter
// to its own Companion Object
companion object : Encodable<EncodableClass> {
override fun EncodableClass.encode(): String {
//You can access (private) fields here
return "This is a string representation of the class with value: $someValue"
}
override fun decode(stringRepresentation: String): EncodableClass {
return EncodableClass(stringRepresentation)
}
}
}
//You also have to import the encode function separately:
// import codingProtocol.EncodableClass.Companion.encode
This is the more optimal use case for me. Instead of one function in the instanced object and the other in the companion object like your example, we move both functions to the companion object and extend the instance.
In a companion object, I want to have a field recording all the instances instantiated from the companion class (it is abstract), can I do that?
Especially, I thought this would reference to any instances of the subclass, but it won't compile when I use it in a companion object.
You'd need to code it yourself, for instance (not thread safe):
abstract class C {
// executed by all subclasses during construction
C.registerInstance(this)
}
object C {
private val instances = ListBuffer[C]()
def registerInstance(c: C) {
instances += c
}
}
this in an object (doesn't matter if it's a companion object or not) refers to the object. E.g.
scala> object A { def foo = 1; def bar = this.foo }
defined module A
scala> A.bar
res0: Int = 1