is it possible for scala superclass return this as subclass - scala

abstract class SuperClass {
def method() = this
}
class SubClass1 extends SuperClass {
def method1() = this
}
class SubClass2 extends SuperClass {
def method2() = this
}
val obj1 = new SubClass1()
obj1.method1().method() // this is ok
val obj2 = new SubClass2()
obj2.method().method2() // this is not ok, as method returns a SuperClass,
// which has no method named method2
So how to make the method return the subclass type so I can chain the operation in any order.
So far what I can think is to follow something like
abstract class SuperClass[T <: SuperClass[T]]
but I don't know how to continue that.

Something like this should work:
abstract class SuperClass {
def method(): this.type = this
}

I find the following approach works as well:
abstract class SuperClass[T <: SuperClass[T]] {
def method(): T = this.asInstanceOf[T]
}
class SubClass extends SuperClass[SubClass] {
def method1() = this
}
val obj = new SubClass()
obj.method1().method()
obj.method().method1()

Related

Scala: force subclasses to override inherited implementation of a method

I want to define a trait that forces its subtypes to override say thetoString method.
Can I do that?
In the more generic case:
trait Old {
def foo: String = "oldFoo"
}
trait New {
//some statement which would result in "oldFoo" disappearing
}
trait New1 extend New {
def foo: String = "new1Foo"
} //should compile
trait New2 extend New //shouldn't compile
I don't think what you want to do is possible, but this workaround could work
trait Old {
def foo: String = "oldFoo"
}
trait New extends Old {
override final def foo: String = newFoo
def newFoo: String
}
class New1 extends New {
override def newFoo: String = "new1Foo"
} // Compiles
class New2 extends New // Don't compiles
trait NewExtra extends New // Compiles, but any sub class of NewExtra is required to implement newFoo

Scala: access "static" member of bounded generic type

I want to achieve the following:
abstract class Super {
def typeSpecific: Int
}
class SubA extends Super {
def typeSpecific = 1
}
class SubB extends Super {
def typeSpecific = 2
}
class Tester[T <: Super] {
def test = T.typeSpecific
}
val testerA = new Tester[SubA]
val testerB = new Tester[SubB]
testerA.test // should return 1
testerB.test // should return 2
Is something like this possible in Scala? This fails because the value of T is not found in Tester.test.
typeSpecific is not a static member, it belongs to instances of SubA and SubB, which you don't have. You also can't statically access anything from a type parameter (it's a type, not an object).
This won't work as is, because you don't have instances of SubA and SubB, nor can you obtain them via new Tester[SubA]. But you can require that Tester mixes in a type of Super in order to make it one (and thus have typeSpecific). This would require you change Super, SubA, and SubB to traits, and would also make your instance anonymous classes.
trait Super {
def typeSpecific: Int
}
trait SubA extends Super {
def typeSpecific = 1
}
trait SubB extends Super {
def typeSpecific = 2
}
// The self-type `this: A =>` requires the mix-in.
class Tester[A <: Super] { this: A =>
def test = typeSpecific
}
val testerA = new Tester[SubA] with SubA
val testerB = new Tester[SubB] with SubB
scala> testerA.test
res2: Int = 1
scala> testerB.test
res3: Int = 2
You could also require A <: Super as a constructor parameter for Tester, which is probably the cleaner option.
abstract class Super {
def typeSpecific: Int
}
class SubA extends Super {
def typeSpecific = 1
}
class SubB extends Super {
def typeSpecific = 2
}
class Tester[A <: Super](s: A) {
def test = s.typeSpecific
}
val testerA = new Tester(new SubA)
val testerB = new Tester(new SubB)
scala> testerA.test
res5: Int = 1
scala> testerB.test
res6: Int = 2
Any way you cut it, you're going to need an instance of SubA or SubB.
You're going to have to use reflection combined with typeTags to get your desired result. I warn you, it's somewhat ugly:
import scala.reflect.runtime.universe._
abstract class SuperClass {
def typeSpecific: Int
}
class SubA extends SuperClass {
def typeSpecific = 1
}
class SubB extends SuperClass {
def typeSpecific = 2
}
class Tester[T <: SuperClass: TypeTag] {
def test = typeTag[T].mirror.runtimeClass(typeOf[T]).newInstance.asInstanceOf[T].typeSpecific
}
I also feel I should mention that typeSpecific is not static as it is part of a class, in scala static members are defined in objects/companion objects only. Using objects it would be cleaner to do something like this:
trait SuperTrait {
def typeSpecific: Int
}
object SubA extends SuperTrait {
def typeSpecific = 1
}
object SubB extends SuperTrait {
def typeSpecific = 2
}
class Tester(testObject : SuperTrait) {
def test = testObject.typeSpecific
}
new Tester(SubA).test
new Tester(SubB).test

Scala 2.11 override things form an abstract class

I have a question concerning Scala override (as my title suggests)
Now I have the following classes/traits:
trait FSM {def transitionGraph:Map[String,(JsValue,FSM)]
abstract class AClass: FSM { def transitionGraph }
class Class extends AClass{ override def transitionGraph ... } <-- Wont work
trait OverrideTrait extends AClass { abstract override def transitionGraph } <-- works
class NewClass extends OverrideTrait { } <--- Works, I can use the overridden transitionGraph
My question is: Why can I not override things from an abstract class. Is it because I am never allowed to instantiate an abstract class. Thus the behavior :
val AClass class = new Class
is never allowed to happen?
Thanks.
There seems to be a lot of stuff omitted from the code you've given, so I'm not sure I get the question, but here's something similar that does compile:
trait FSM { def transitionGraph: String }
abstract class AClass extends FSM { def transitionGraph: String }
class Class extends AClass { override def transitionGraph = ??? }
trait OverrideTrait extends AClass { override def transitionGraph = ??? }
class NewClass extends OverrideTrait { }
Does this help at all?
Your code example wouldn't compile. But it should work once you corrected a few things:
trait FSM {def transitionGraph:Map[String,(JsValue,FSM)]}
abstract class AbstractClass extends FSM { def transitionGraph }
class ConcreteClass extends AbstractClass{ def transitionGraph = ??? }
val someClass: AbstractClass = new ConcreteClass

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
}
}

programmatically setting the `type` of an abstract type

class MyModel(var username:String, var password:String) extends FrameworkModel
object MyModelQuery extends FrameworkQuery {
type T = MyModel
}
trait FrameworkQuery {
type T
//do something with that type
}
So I get a class and an object where the latter is mixing in a trait which is defined as an abstract type. Is there a way I could programmatically set the type to the type of MyModel class, so the client would not need to? ie "object MyModelQuery extends FrameworkQuery" would take care of it
Could you achieve a similar effect by just nesting the query in the model?
trait FrameworkModel {
val model = this
trait FrameworkQuery {
type T = model.type
def getModel: T = model
}
}
class UserModel extends FrameworkModel {
// model stuff...
object UserQuery extends FrameworkQuery {
// query stuff...
}
}
trait T{
type X = this.type
def x: X = this
}
object A extends T{
def b = "Yep"
}
scala> A.x.b
res0: java.lang.String = Yep