How to share functionality between subclasses - scala

I would like subclasses to inject functionality within the base class' apply method:
Base class:
case class BaseClass(data: Json)
object BaseClass {
def apply(data: String) : JsonClass = {
try {
_ //subclass functionality should go here
} catch {
case e: Exception => ErrorJsonClass(data)
}
}
}
object SubClass extends BaseClass {
def apply(data: String) : Json = {
deserialize(data) // this should be called within the base class' apply
}
}
Is there a way to do this without declaring separate methods within the base class?
Ie. Im trying to avoid the following:
object BaseClass {
def apply(data: String) : JsonClass = {
try {
convert(data)
} catch {
case e: Exception => ErrorJsonClass(data)
}
}
def convert(data: String): JsonClass = _
}
object SubClass extends BaseClass {
def convert(data: String) : Json = {
deserialize(data)
}
}

Related

Scala - Invoking a class by string (with class name)

I have those classes like this:
object Class1 extends parent {
def execute() {
print("Class1")
}
}
object Class2 extends parent {
def execute {
print("Class2")
}
}
Then I have a Runner like this:
object Runner extends runParent {
def manageRun(className: String) = {
def ClassInstance = className match {
case Some("Class1") => Some(Class1)
case Some("Class2") => Some(Class2)
}
ClassInstance.execute()
}
}
There is any way to change this managerRun code and when I create a Class3 I don't need to add a new case in the match?
Thanks!

Define method that could be accessed only from descendants within the same package

I'd like to specify somehow that a method could be accessed only from descendants that are defined in the same package. That is like protected but more restricted.
object Some {
class Base {
modifier[magic] def test() {
println("ok")
}
}
class Ok extends Base {
test()
}
class ShouldFail {
def fail(b : Base) {
b.test()
}
}
}
object Another {
class ShouldFail extends Some.Base {
test()
}
}
That is what I'd like to get
I've got a solution, too verbose and with some overhead for accessing protected methods.
object Some {
private[Some] class Access[T] private[Some] (aFun : () => T) {
private[Some] def apply() : T = aFun()
}
private[Some] object Access {
private[Some] def apply[T](aFun : () => T) : Access[T] = new Access(aFun)
}
class Base {
private[this] def test() {
println("ok")
}
protected val accessTest = Access( () => test() )
}
class Ok extends Base {
accessTest()
}
class ShouldFail {
def fail(b : Base) {
b.accessTest()
}
}
}
object Another {
class ShouldFail extends Some.Base {
accessTest()
}
}
The idea is to wrap method inside an object and chain permission restrictions between access modifiers for accessing object and accessing value inside object. That introduces overhead, though.

Is there a way in scala using functionality from super class in mixed in trait

I have the following classes/traits setup:
class RestService extends EntityReader[UserEntity]
with EntityReaderExtension {
def serveSomething() = {...}
}
trait EntityReader[EntityType <: StoredEntity] extends RestHelper {
protected def read(id:UUID): Option[EntityType] = {
// Read by id
}
}
trait EntityReaderExtension {
def serveExtensionMethod(id:UUID) = {
// val entity = read(id) match {...}
// copy values to other entity and serve
}
}
Is there a way i can use the method from trait EntityReader in trait EntityReaderExtension without extending?
I think what you want is an explicitly typed self reference.
trait EntityReaderExtension { self: EntityReader[_] =>
def serveExtensionMethod(id:UUID) = {
val entity = self.read(id) match {...}
}
}

How to extend an object in Scala with an abstract class with constructor?

How to extend an object in Scala with an abstract class that has a constructor, and apply method of the object returns the object as subtype of the abstract?
for example :
abstract class AbstractResource(amount:Int) {
val amount:Int
def getAmount = amount
}
case object Wood extends AbstractResource{
def apply(amount: Int) = {
// something that returns the subtype
}
}
I think a good solution is:
abstract class AbstractResource {
val amount: Int = 0
def getAmount = amount
}
case object Wood extends AbstractResource {
def apply(quantity: Int) = {
new AbstractResource {
override val amount = quantity
}
}
}
But my problem is I can't edit AbstractResource
I have no idea why should Wood extend AbstractResource, but this works:
class AbstractResource(val amount:Int) {
def getAmount = amount
}
case object Wood extends AbstractResource(0) {
def apply(amount: Int) = {
new AbstractResource(amount)
}
}

Returning the same type the function was passed

I have the following code implementation of Breadth-First search.
trait State{
def successors:Seq[State]
def isSuccess:Boolean = false
def admissableHeuristic:Double
}
def breadthFirstSearch(initial:State):Option[List[State]] = {
val open= new scala.collection.mutable.Queue[List[State]]
val closed = new scala.collection.mutable.HashSet[State]
open.enqueue(initial::Nil)
while (!open.isEmpty){
val path:List[State]=open.dequeue()
if(path.head.isSuccess) return Some(path.reverse)
closed += path.head
for (x <- path.head.successors)
if (!closed.contains(x))
open.enqueue(x::path)
}
return None
}
If I define a subtype of State for my particular problem
class CannibalsState extends State {
//...
}
What's the best way to make breadthFirstSearch return the same subtype as it was passed?
Supposing I change this so that there are 3 different state classes for my particular problem and they share a common supertype:
abstract class CannibalsState extends State {
//...
}
class LeftSideOfRiver extends CannibalsState {
//...
}
class InTransit extends CannibalsState {
//...
}
class RightSideOfRiver extends CannibalsState {
//...
}
How can I make the types work out so that breadthFirstSearch infers that the correct return type is CannibalsState when it's passed an instance of LeftSideOfRiver?
Can this be done with an abstract type member, or must it be done with generics?
One option is to use generics as Randall described. If you want to achieve something similar with an abstract type member, then you can do it like this (based on Mitch's code):
trait ProblemType {
type S <: State
trait State {
def successors: Seq[S]
def isSuccess: Boolean = false
def admissableHeuristic: Double
}
def breadthFirstSearch(initial: S): Option[List[S]] = {
val open = new scala.collection.mutable.Queue[List[S]]
val closed = new scala.collection.mutable.HashSet[S]
open.enqueue(initial :: Nil)
while (!open.isEmpty) {
val path: List[S] = open.dequeue()
if (path.head.isSuccess) return Some(path.reverse)
closed += path.head
for (x <- path.head.successors)
if (!closed.contains(x))
open.enqueue(x :: path)
}
return None
}
}
object RiverCrossingProblem extends ProblemType {
type S = CannibalsState
abstract class CannibalsState extends State {
//...
}
class LeftSideOfRiver extends CannibalsState {
//...
}
class InTransit extends CannibalsState {
//...
}
class RightSideOfRiver extends CannibalsState {
//...
}
}
How about this?
trait State[+S] {
def successors: Seq[State[S]]
def isSuccess: Boolean = false
def admissableHeuristic: Double
}
object BFS
{
def
breadthFirstSearch[S <: State[S]](initial: State[S]): Option[List[State[S]]] = {
val open= new scala.collection.mutable.Queue[List[State[S]]]
val closed = new scala.collection.mutable.HashSet[State[S]]
open.enqueue(initial :: Nil)
while (!open.isEmpty) {
val path: List[State[S]] = open.dequeue()
if (path.head.isSuccess)
return Some(path.reverse)
closed += path.head
for (x <- path.head.successors)
if (!closed.contains(x))
open.enqueue(x :: path)
}
return None
}
}
One approach to this type of problem is to enclose the State trait and the operations that act on it within another trait.
trait ProblemType {
trait State {
def successors: Seq[State]
def isSuccess: Boolean = false
def admissableHeuristic: Double
}
def breadthFirstSearch(initial: State): Option[List[State]] = {
val open = new scala.collection.mutable.Queue[List[State]]
val closed = new scala.collection.mutable.HashSet[State]
open.enqueue(initial :: Nil)
while (!open.isEmpty) {
val path: List[State] = open.dequeue()
if (path.head.isSuccess) return Some(path.reverse)
closed += path.head
for (x <- path.head.successors)
if (!closed.contains(x))
open.enqueue(x :: path)
}
return None
}
}
Then, you can define your concrete States within an object extending the enclosing trait:
object RiverCrossingProblem extends ProblemType {
class LeftSideOfRiver extends State {
// ...
}
class InTransit extends State {
// ...
}
class RightSideOfRiver extends State {
// ...
}
}