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

using this.type

5 replies
Russ P.
Joined: 2009-01-31,
User offline. Last seen 1 year 26 weeks ago.
I have a class called Scalar, which represents physical scalars (physical quantities with units). It has fields called "num" for the quantity and "units" for the physical units. It has a "+" method that looks something like this (slightly simplified here):

        def + (that: Scalar): Scalar = {

            checkUnits(that)
            new Scalar(num + that.num, units)
            }

Now suppose I decide that I want to extend Scalar to create specific types of Scalars, such as Time, Length, etc.,  so I do this:

    case class Time(s: Scalar) extends Scalar(s)

I don't want to get into a general discussion here of the static type checking for units, but it occurred to me that I might be able to get at least some static checking. The problem is that my + method returns a Scalar, not a Time. So I changed it to this:

        def + (that: this.type): this.type = {

            checkUnits(that)
            new Scalar(num + that.num, units).asInstanceOf[this.type]
            }

However, this causes all sorts of compilation errors, such as

[error] ACmodels.scala:438: type mismatch;
[error]  found   : dt.type (with underlying type scalar.package.Scalar)
[error]  required: _1.type where val _1: scalar.package.Scalar
[error]         val time1 = time + dt

I don't understand this. It's telling me there's a type mismatch, but both types are scalar.package.Scalar. Is this a compiler bug? Is there a way to do this sort of thing? Thanks.

--Russ P.

--
http://RussP.us
ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: using this.type
this.type is not a MyType, it is the unique type of that single instantiated copy of that class.

Thus, taking it as a parameter is a bit weird, since you already have it, since you're in one of its methods!  (If a parameter has type this.type, then the value of that parameter is guaranteed to be this.)

Scala doesn't have a MyType facility which, roughly speaking, would match what this.getClass would show.

  --Rex

On Sun, Jan 29, 2012 at 6:06 PM, Russ Paielli <russ.paielli@gmail.com> wrote:
I have a class called Scalar, which represents physical scalars (physical quantities with units). It has fields called "num" for the quantity and "units" for the physical units. It has a "+" method that looks something like this (slightly simplified here):

        def + (that: Scalar): Scalar = {

            checkUnits(that)
            new Scalar(num + that.num, units)
            }

Now suppose I decide that I want to extend Scalar to create specific types of Scalars, such as Time, Length, etc.,  so I do this:

    case class Time(s: Scalar) extends Scalar(s)

I don't want to get into a general discussion here of the static type checking for units, but it occurred to me that I might be able to get at least some static checking. The problem is that my + method returns a Scalar, not a Time. So I changed it to this:

        def + (that: this.type): this.type = {

            checkUnits(that)
            new Scalar(num + that.num, units).asInstanceOf[this.type]
            }

However, this causes all sorts of compilation errors, such as

[error] ACmodels.scala:438: type mismatch;
[error]  found   : dt.type (with underlying type scalar.package.Scalar)
[error]  required: _1.type where val _1: scalar.package.Scalar
[error]         val time1 = time + dt

I don't understand this. It's telling me there's a type mismatch, but both types are scalar.package.Scalar. Is this a compiler bug? Is there a way to do this sort of thing? Thanks.

--Russ P.

--
http://RussP.us

Lars Hupel
Joined: 2010-06-23,
User offline. Last seen 44 weeks 3 days ago.
Re: using this.type

> def + (that: this.type): this.type = {
>
> checkUnits(that)
> new Scalar(num + that.num, units).asInstanceOf[this.type]
> }

This signature doesn't make sense, and it is dangerous. As Rex pointed
out, if a value has type `p.type`, then the value *is* `p`, and it is
the only value of `p.type`. So, don't cast something to `this.type`.

The usual approach for what you want to do is:

trait Super[Self <: Super] {
def +(that: Self)
}

trait Sub extends Super[Sub] {
//...
}

(You could also have `Self` as a type member instead.)

Russ P.
Joined: 2009-01-31,
User offline. Last seen 1 year 26 weeks ago.
Re: using this.type

Thanks, Rex, but I'd still like to know if there is a way to get what
I want. I realize that I can override the + method (and other similar
methods) for the Time class and every other such class that I decide
to create, but that would involve a lot of repetition. Is that what I
need to do? It would be much better to be able to handle it once and
for all in the Scalar class. Is that possible?

--Russ P.

On Jan 29, 4:14 pm, Rex Kerr wrote:
> this.type is not a MyType, it is the unique type of that single
> instantiated copy of that class.
>
> Thus, taking it as a parameter is a bit weird, since you already have it,
> since you're in one of its methods!  (If a parameter has type this.type,
> then the value of that parameter is guaranteed to be this.)
>
> Scala doesn't have a MyType facility which, roughly speaking, would match
> what this.getClass would show.
>
>   --Rex
>
> On Sun, Jan 29, 2012 at 6:06 PM, Russ Paielli wrote:
>
>
>
>
>
>
>
> > I have a class called Scalar, which represents physical scalars (physical
> > quantities with units). It has fields called "num" for the quantity and
> > "units" for the physical units. It has a "+" method that looks something
> > like this (slightly simplified here):
>
> >         def + (that: Scalar): Scalar = {
>
> >             checkUnits(that)
> >             new Scalar(num + that.num, units)
> >             }
>
> > Now suppose I decide that I want to extend Scalar to create specific types
> > of Scalars, such as Time, Length, etc.,  so I do this:
>
> >     case class Time(s: Scalar) extends Scalar(s)
>
> > I don't want to get into a general discussion here of the static type
> > checking for units, but it occurred to me that I might be able to get at
> > least some static checking. The problem is that my + method returns a
> > Scalar, not a Time. So I changed it to this:
>
> >         def + (that: this.type): this.type = {
>
> >             checkUnits(that)
> >             new Scalar(num + that.num, units).asInstanceOf[this.type]
> >             }
>
> > However, this causes all sorts of compilation errors, such as
>
> > [error] ACmodels.scala:438: type mismatch;
> > [error]  found   : dt.type (with underlying type scalar.package.Scalar)
> > [error]  required: _1.type where val _1: scalar.package.Scalar
> > [error]         val time1 = time + dt
>
> > I don't understand this. It's telling me there's a type mismatch, but both
> > types are scalar.package.Scalar. Is this a compiler bug? Is there a way to
> > do this sort of thing? Thanks.
>
> > --Russ P.
>
> > --
> >http://RussP.us

Chris Twiner
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: using this.type

Yes its possible, if not a bit boilerplatey:

http://code.google.com/p/scala-scales/wiki/VirtualConstructorPreSIP

It can't yet be implemented via a compiler plugin (the lensed approach via sbt could be doable though) so its all manual I'm afraid.

On Jan 30, 2012 2:42 AM, "Russ P." <russ.paielli@gmail.com> wrote:
Thanks, Rex, but I'd still like to know if there is a way to get what
I want. I realize that I can override the + method (and other similar
methods) for the Time class and every other such class that I decide
to create, but that would involve a lot of repetition. Is that what I
need to do? It would be much better to be able to handle it once and
for all in the Scalar class. Is that possible?

--Russ P.


On Jan 29, 4:14 pm, Rex Kerr <icho...@gmail.com> wrote:
> this.type is not a MyType, it is the unique type of that single
> instantiated copy of that class.
>
> Thus, taking it as a parameter is a bit weird, since you already have it,
> since you're in one of its methods!  (If a parameter has type this.type,
> then the value of that parameter is guaranteed to be this.)
>
> Scala doesn't have a MyType facility which, roughly speaking, would match
> what this.getClass would show.
>
>   --Rex
>
> On Sun, Jan 29, 2012 at 6:06 PM, Russ Paielli <russ.paie...@gmail.com>wrote:
>
>
>
>
>
>
>
> > I have a class called Scalar, which represents physical scalars (physical
> > quantities with units). It has fields called "num" for the quantity and
> > "units" for the physical units. It has a "+" method that looks something
> > like this (slightly simplified here):
>
> >         def + (that: Scalar): Scalar = {
>
> >             checkUnits(that)
> >             new Scalar(num + that.num, units)
> >             }
>
> > Now suppose I decide that I want to extend Scalar to create specific types
> > of Scalars, such as Time, Length, etc.,  so I do this:
>
> >     case class Time(s: Scalar) extends Scalar(s)
>
> > I don't want to get into a general discussion here of the static type
> > checking for units, but it occurred to me that I might be able to get at
> > least some static checking. The problem is that my + method returns a
> > Scalar, not a Time. So I changed it to this:
>
> >         def + (that: this.type): this.type = {
>
> >             checkUnits(that)
> >             new Scalar(num + that.num, units).asInstanceOf[this.type]
> >             }
>
> > However, this causes all sorts of compilation errors, such as
>
> > [error] ACmodels.scala:438: type mismatch;
> > [error]  found   : dt.type (with underlying type scalar.package.Scalar)
> > [error]  required: _1.type where val _1: scalar.package.Scalar
> > [error]         val time1 = time + dt
>
> > I don't understand this. It's telling me there's a type mismatch, but both
> > types are scalar.package.Scalar. Is this a compiler bug? Is there a way to
> > do this sort of thing? Thanks.
>
> > --Russ P.
>
> > --
> >http://RussP.us
Chris Marshall
Joined: 2009-06-17,
User offline. Last seen 44 weeks 3 days ago.
RE: Re: using this.type
See recent posting by Paul - the compiler knows but it isn't telling!  http://comments.gmane.org/gmane.comp.lang.scala.debate/8570 

> Date: Sun, 29 Jan 2012 17:42:43 -0800
> Subject: [scala-user] Re: using this.type
> From: russ.paielli@gmail.com
> To: scala-user@googlegroups.com
>
> Thanks, Rex, but I'd still like to know if there is a way to get what
> I want. I realize that I can override the + method (and other similar
> methods) for the Time class and every other such class that I decide
> to create, but that would involve a lot of repetition. Is that what I
> need to do? It would be much better to be able to handle it once and
> for all in the Scalar class. Is that possible?
>
> --Russ P.

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