Reuse a case class inside an object in scala - scala

I have an object that contains one or more case classes and associated methods. I would like to reuse this case class within another object (which has similar characteristics as this object but also some differentiating methods).
private object abc {
/* ... */
case class xyz(..) { def someFunc(){} }
object xyz { def apply() {} }
}
private object extendabc {
// How to reuse case class xyz here?
}

If you want to just access you can use this kind of a code .
private object abc {
case class xyz() {
def someFunc(){}
}
object xyz { }
}
private object extendabc {
val a = new abc.xyz()
a.someFunc()
}
You need to call this way because xyz is a nested member of the object abc .
Look here.
Also please note you cannot define a apply method in the companion object of a case class as it provides the exact same apply() method (with the same signature.

Related

Create sublass instance from ancestor

i am quite new in Scala. Have class named 'Document' and a few classes, like 'Doc1' and 'Doc2' which are children of Document. So:
abstract class Document(id: Int, xmlString: String) {
// make some operations and create an instance of subtype
}
case class Doc1 extends Document {
// some subclass specific methods
}
case class Doc2 extends Document {
// some subclass specific methods
}
Would like to run Document constructor and as a result, create an instance of Doc1 or Doc2 conditionally due to passed paramethers. Shall i add some auxiliary constructors in 'Document' class?
Any idea welcome.
The best practice is to use companion object/singleton object:
abstract class Document { ... }
object Document {
def apply(docType: String) = {
if (docType == "doc1") {
Doc1()
} else {
Doc2()
}
}
}
and the usage of it:
val document1 = Document("doc1")
Of course, it's just a simple example - you can change the docType to sealed class and check the type by pattern matching.
Update - by #crater2150 comment - you can use the apply instead of different function name, so you will write Document("doc1") instead of Document.someFunctionName("doc1")

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

Is it possible to specify a static function in a Kotlin interface?

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.

How do I stub out a protected method in a object in scala

Example:
object Test {
def test = {
doTest
}
protected def doTest = {
// do something
}
}
class MockTest extends WordSpec with Mockito{
"" in {
val t = spy(Test)
// how do i stub out doTest?
}
}
I have a Test class with a protected doTest method. How do I stub out this protected method?
I would advise to make doTest package private, so that clients of your object won't be able to call it, but you'll be able to test it from within the same package.
package com.company.my.foo
object Test {
def test = {
doTest
}
private[foo] def doTest = {
// do something
}
}
and
package com.company.my.foo
class MockTest extends WordSpec with Mockito{
"" in {
val t = spy(Test)
when(t.doTest()).thenReturn("foo")
}
}
Test is a singleton (all Scala objects are), you can subclass a class, but not an object. Hence protected is a bit meaningless here - you're saying this method should only be accessible to subclasses, but it's not possible to have any (since Test is an object).
You have a couple options depending on what is best suited to your needs. 1) you can make Test a class and then extend it, or 2) change the access level of doTest to public [which is the default in Scala if you don't specify an access modifier]

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