This page is no longer maintained — Please continue to the home page at www.scala-lang.org

How to get around of invariance of MongoRecord in Scala

3 replies
Lucas Wang
Joined: 2011-10-16,
User offline. Last seen 42 years 45 weeks ago.

Say I have a class defined as follows:

class A extends MongoRecord[A]{

}
Now I need to create a new class B, that is a subclass of A:

class B extends A{

}
Object B extends B with MongoMetaRecord[B]

The compiler would give an error like: type arguments [B] do not
conform to trait MongoMetaRecord's type parameter bounds [BaseRecord
<: net.liftweb.mongodb.record.MongoRecord[BaseRecord]]
[error] object B extends B with MongoMetaRecord[B]

It seems that the class B inherits MongoRecord[A], but because of the
invariance of MongoRecord, MongoRecord[B] cannot substitute
MongoRecord[A]. And therefore class B does not conform to the type
constraint. Any idea how to get around this problem? Thanks a lot.

d_m
Joined: 2010-11-11,
User offline. Last seen 35 weeks 2 days ago.
Re: How to get around of invariance of MongoRecord in Scala

On Sat, Oct 15, 2011 at 05:23:10PM -0700, Lucas Wang wrote:
> Say I have a class defined as follows:
>
> class A extends MongoRecord[A]{
>
> }
> Now I need to create a new class B, that is a subclass of A:
>
> class B extends A{
>
> }
> Object B extends B with MongoMetaRecord[B]

Hi Lucas,

In my opinion the easiest way to fix this would be to create a trait
with A's implementation (call it whatever you want, say Impl) which
does not extend MongoRecord[A]. Then your definitions can be:

class A extends MongoRecord[A] with Impl { ... }

class B extends MongoRecord[B] with Impl { ... }

When writing Scala I find myself making most of my (non-abstract)
classes final, and using traits to share implementation. In these cases
it's easier to dodge inheritance issues like this one.

Ben Hutchison 3
Joined: 2009-11-02,
User offline. Last seen 42 years 45 weeks ago.
Re: How to get around of invariance of MongoRecord in Scala

On Sun, Oct 16, 2011 at 11:23 AM, Lucas Wang wrote:
> class A extends MongoRecord[A]{
>
> }
> Now I need to create a new class B, that is a subclass of A:
>
> class B extends A{
>
> }
> Object B extends B with MongoMetaRecord[B]
>
> The compiler would give an error like: type arguments [B] do not
> conform to trait MongoMetaRecord's type parameter bounds [BaseRecord
> <: net.liftweb.mongodb.record.MongoRecord[BaseRecord]]
> [error] object B extends B with MongoMetaRecord[B]
>
> It seems that the class B inherits MongoRecord[A], but because of the
> invariance of MongoRecord, MongoRecord[B] cannot substitute
> MongoRecord[A]. And therefore class B does not conform to the type
> constraint. Any idea how to get around this problem? Thanks a lot.
>
Hi Lucas,

I dont know how MongoRecord works, but if its mutable it has to be
invariant to be typesafe. See Array Variance here for an example
[http://www.artima.com/pins1ed/type-parameterization.html#19.3]

I like to break up invariant interfaces into separate Covariant and
Contravariant parts, but I realize this isnt an option for you if its
Lift's code.

Basically, MongoRecord isnt designed to support passing a MR[B] as an
MR[A], where B <: A I think you'll need to change your design.

-Ben

vpatryshev
Joined: 2009-02-16,
User offline. Last seen 1 year 24 weeks ago.
Re: How to get around of invariance of MongoRecord in Scala
There's no reason for MongoRecord to be mutable.

Thanks,
-Vlad


On Sun, Oct 16, 2011 at 3:30 PM, Ben Hutchison <brhutchison [at] gmail [dot] com> wrote:
On Sun, Oct 16, 2011 at 11:23 AM, Lucas Wang <wangjiangzhe2007 [at] gmail [dot] com> wrote:
> class A extends MongoRecord[A]{
>
> }
> Now I need to create a new class B, that is a subclass of A:
>
> class B extends A{
>
> }
> Object B extends B with MongoMetaRecord[B]
>
> The compiler would give an error like: type arguments [B] do not
> conform to trait MongoMetaRecord's type parameter bounds [BaseRecord
> <: net.liftweb.mongodb.record.MongoRecord[BaseRecord]]
> [error] object B extends B with MongoMetaRecord[B]
>
> It seems that the class B inherits MongoRecord[A], but because of the
> invariance of MongoRecord, MongoRecord[B] cannot substitute
> MongoRecord[A]. And therefore class B does not conform to the type
> constraint. Any idea how to get around this problem? Thanks a lot.
>
Hi Lucas,

I dont know how MongoRecord works, but if its mutable it has to be
invariant to be typesafe. See Array Variance here for an example
[http://www.artima.com/pins1ed/type-parameterization.html#19.3]

I like to break up invariant interfaces into separate Covariant and
Contravariant parts, but I realize this isnt an option for you if its
Lift's code.

Basically, MongoRecord isnt designed to support passing a MR[B] as an
MR[A], where B <: A I think you'll need to change your design.

-Ben

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland