Convert case class to 'parent'

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Convert case class to 'parent'

Colin Bester
I am needing to cast a subclassed scala object to it's parent's object. 

Essentially I need two case classes, one case class to be thought of as the super class, and the other as the subclassed case class. I am wanting to use this for some database domain objects I am working on.

As you can't subclass case classes I was trying to see if there was a way to accomplish this via subclassed traits.

It may be easiest to show with a code snippet:

In code below, case class MyUserInfo can be thought of as the 'parent' class and case class MyUser can be thought of as the 'subclass'.
 
So I got as far as using asInstanceOf[InfoBase], the trait MyUserInfo is extending, but don't see how to convert this to required type MyUserInfo. As I am wanting to serialize this case class to JSON, I do need it to be of the 'parent' MyUserInfo type.

trait InfoBase{
  def a: Int
  def b: Int
}

trait Base { 
  def c: String
}

case class MyUserInfo(a: Int, b:Int) extends InfoBase
case class MyUser(a: Int, b:Int, c:String) extends InfoBase with Base

object CastTest extends App {
  val user: MyUser = MyUser(1, 2, "3")  
  
  //wish to 'convert' MyUser to it's 'super' class
  val info = user.asInstanceOf[InfoBase]
}

I may be totally on the wrong track here, for now I am using an Implicit where I instantiate a new MyUserInfo case class passing in desired parameters, as

object ModelImplicits {
 
implicit class UserConversion(user: MyUser) {    
 
def toUserInfo: MyUserInfo = MyUserInfo(user.a, user.b)
 
}
}

While this works, it breaks if one ever adds parameters and doesn't update the implicit function, as I found out this morning :-(

Appreciate any suggestions and hope my rambling makes sense.

Thanks
Colin

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Convert case class to 'parent'

Colin Bester
Couldn't see how to edit my original post but wanted to mention that this example is a rather simplified version of what I am trying to do. Reason for having the case classes is to ensure type validity where the same trait is used on RESTful server as on WebApplication server, each being implemented by their own (relevant) case classes, where WebApplication is agnostic of database implementation on RESTful side.

On Saturday, December 20, 2014 1:46:52 PM UTC-6, Colin Bester wrote:
I am needing to cast a subclassed scala object to it's parent's object. 

Essentially I need two case classes, one case class to be thought of as the super class, and the other as the subclassed case class. I am wanting to use this for some database domain objects I am working on.

As you can't subclass case classes I was trying to see if there was a way to accomplish this via subclassed traits.

It may be easiest to show with a code snippet:

In code below, case class MyUserInfo can be thought of as the 'parent' class and case class MyUser can be thought of as the 'subclass'.
 
So I got as far as using asInstanceOf[InfoBase], the trait MyUserInfo is extending, but don't see how to convert this to required type MyUserInfo. As I am wanting to serialize this case class to JSON, I do need it to be of the 'parent' MyUserInfo type.

trait InfoBase{
  def a: Int
  def b: Int
}

trait Base { 
  def c: String
}

case class MyUserInfo(a: Int, b:Int) extends InfoBase
case class MyUser(a: Int, b:Int, c:String) extends InfoBase with Base

object CastTest extends App {
  val user: MyUser = MyUser(1, 2, "3")  
  
  //wish to 'convert' MyUser to it's 'super' class
  val info = user.asInstanceOf[InfoBase]
}

I may be totally on the wrong track here, for now I am using an Implicit where I instantiate a new MyUserInfo case class passing in desired parameters, as

object ModelImplicits {
 
implicit class UserConversion(user: MyUser) {    
 
def toUserInfo: MyUserInfo = MyUserInfo(user.a, user.b)
 
}
}

While this works, it breaks if one ever adds parameters and doesn't update the implicit function, as I found out this morning :-(

Appreciate any suggestions and hope my rambling makes sense.

Thanks
Colin

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Convert case class to 'parent'

Lanny Ripple
Why not actually extend the traits?

trait UserInfo {
  def a: Int
  def b: Int
}

trait User extends UserInfo {
  def c: Int
}

case class MyUserInfo(a: Int, b: Int) extends UserInfo
case class MyUser(a: Int, b: Int, c: Int) extends User

Then all your code should be implemented only with types UserInfo and User.  When you want to create a User which can be used as the parent UserInfo class you use MyUser (but only as a constructor).

Another alternative is to create your classes as classes and have a companion object implement an apply so you can construct the classes without 'new'.  You'd have to write toString and all the other things case classes provide but in a lot of cases those don't get used.  YMMV.

On Saturday, December 20, 2014 3:06:15 PM UTC-6, Colin Bester wrote:
Couldn't see how to edit my original post but wanted to mention that this example is a rather simplified version of what I am trying to do. Reason for having the case classes is to ensure type validity where the same trait is used on RESTful server as on WebApplication server, each being implemented by their own (relevant) case classes, where WebApplication is agnostic of database implementation on RESTful side.

On Saturday, December 20, 2014 1:46:52 PM UTC-6, Colin Bester wrote:
I am needing to cast a subclassed scala object to it's parent's object. 

Essentially I need two case classes, one case class to be thought of as the super class, and the other as the subclassed case class. I am wanting to use this for some database domain objects I am working on.

As you can't subclass case classes I was trying to see if there was a way to accomplish this via subclassed traits.

It may be easiest to show with a code snippet:

In code below, case class MyUserInfo can be thought of as the 'parent' class and case class MyUser can be thought of as the 'subclass'.
 
So I got as far as using asInstanceOf[InfoBase], the trait MyUserInfo is extending, but don't see how to convert this to required type MyUserInfo. As I am wanting to serialize this case class to JSON, I do need it to be of the 'parent' MyUserInfo type.

trait InfoBase{
  def a: Int
  def b: Int
}

trait Base { 
  def c: String
}

case class MyUserInfo(a: Int, b:Int) extends InfoBase
case class MyUser(a: Int, b:Int, c:String) extends InfoBase with Base

object CastTest extends App {
  val user: MyUser = MyUser(1, 2, "3")  
  
  //wish to 'convert' MyUser to it's 'super' class
  val info = user.asInstanceOf[InfoBase]
}

I may be totally on the wrong track here, for now I am using an Implicit where I instantiate a new MyUserInfo case class passing in desired parameters, as

object ModelImplicits {
 
implicit class UserConversion(user: MyUser) {    
 
def toUserInfo: MyUserInfo = MyUserInfo(user.a, user.b)
 
}
}

While this works, it breaks if one ever adds parameters and doesn't update the implicit function, as I found out this morning :-(

Appreciate any suggestions and hope my rambling makes sense.

Thanks
Colin

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Convert case class to 'parent'

Colin Bester
That's pretty much what I had, only difference I see is that trait User extends UserInfo, where in my case class I extended UserInfo with User.

Problem is that val info = user.asInstanceOf[InfoBase] doesn't convert to MyUserInfo, a simple info.getClass() shows that type is still MyUser so all serialization methods (used by case class to json libraries) still process all three variables (a,b,c) and not just a,b.

Problem is that you can't do a cast to MyUser as MyUserInfo is not super class of MyUser. 

I have messed around with using class extending abstract class and writing my own companion objects with not much success and seems to be more complicated than necessary.

On Saturday, December 20, 2014 6:20:17 PM UTC-6, Lanny Ripple wrote:
Why not actually extend the traits?

trait UserInfo {
  def a: Int
  def b: Int
}

trait User extends UserInfo {
  def c: Int
}

case class MyUserInfo(a: Int, b: Int) extends UserInfo
case class MyUser(a: Int, b: Int, c: Int) extends User

Then all your code should be implemented only with types UserInfo and User.  When you want to create a User which can be used as the parent UserInfo class you use MyUser (but only as a constructor).

Another alternative is to create your classes as classes and have a companion object implement an apply so you can construct the classes without 'new'.  You'd have to write toString and all the other things case classes provide but in a lot of cases those don't get used.  YMMV.

On Saturday, December 20, 2014 3:06:15 PM UTC-6, Colin Bester wrote:
Couldn't see how to edit my original post but wanted to mention that this example is a rather simplified version of what I am trying to do. Reason for having the case classes is to ensure type validity where the same trait is used on RESTful server as on WebApplication server, each being implemented by their own (relevant) case classes, where WebApplication is agnostic of database implementation on RESTful side.

On Saturday, December 20, 2014 1:46:52 PM UTC-6, Colin Bester wrote:
I am needing to cast a subclassed scala object to it's parent's object. 

Essentially I need two case classes, one case class to be thought of as the super class, and the other as the subclassed case class. I am wanting to use this for some database domain objects I am working on.

As you can't subclass case classes I was trying to see if there was a way to accomplish this via subclassed traits.

It may be easiest to show with a code snippet:

In code below, case class MyUserInfo can be thought of as the 'parent' class and case class MyUser can be thought of as the 'subclass'.
 
So I got as far as using asInstanceOf[InfoBase], the trait MyUserInfo is extending, but don't see how to convert this to required type MyUserInfo. As I am wanting to serialize this case class to JSON, I do need it to be of the 'parent' MyUserInfo type.

trait InfoBase{
  def a: Int
  def b: Int
}

trait Base { 
  def c: String
}

case class MyUserInfo(a: Int, b:Int) extends InfoBase
case class MyUser(a: Int, b:Int, c:String) extends InfoBase with Base

object CastTest extends App {
  val user: MyUser = MyUser(1, 2, "3")  
  
  //wish to 'convert' MyUser to it's 'super' class
  val info = user.asInstanceOf[InfoBase]
}

I may be totally on the wrong track here, for now I am using an Implicit where I instantiate a new MyUserInfo case class passing in desired parameters, as

object ModelImplicits {
 
implicit class UserConversion(user: MyUser) {    
 
def toUserInfo: MyUserInfo = MyUserInfo(user.a, user.b)
 
}
}

While this works, it breaks if one ever adds parameters and doesn't update the implicit function, as I found out this morning :-(

Appreciate any suggestions and hope my rambling makes sense.

Thanks
Colin

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Convert case class to 'parent'

Jerzy Muller
Casting only changes the compile-time type, not the runtime one. And dispatch on the JVM is done in runtime, no amount of casting will change the underlying implementation.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.