Thread overview
[Issue 1835] New: typeof(this) should return the type of object or some other typeof() is needed
Feb 14, 2008
d-bugmail
Feb 14, 2008
d-bugmail
Feb 14, 2008
d-bugmail
Feb 14, 2008
d-bugmail
Feb 14, 2008
d-bugmail
Aug 20, 2008
d-bugmail
Jul 24, 2010
Simen Kjaeraas
Jul 24, 2010
Christian Kamm
Jul 24, 2010
Fawzi Mohamed
February 14, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1835

           Summary: typeof(this) should return the type of object or some
                    other typeof() is needed
           Product: D
           Version: unspecified
          Platform: Other
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla@digitalmars.com
        ReportedBy: onlystupidspamhere@yahoo.se


Consider the following code:

class A {
  A foo() { return this; }
}

class B : A {
  B bar() { return this; }
}

void main() {
  auto b = new B;
  b.foo().bar(); // We would like to chain methods like this
}

Currently this is not possible without CRTP (fugly) / mixins (not a good idea)
/ casts (yucky). Also typeof(this) returns A in class A.. Why can't we allow
this:

class A {
  typeof(this) foo() { return this; } // here the return type would depend on
the actual runtime type of the object
}

class B : A {
  B bar() { return this; }
}

void main() {
  auto b = new B;
  b.foo().bar(); // We would like to chain methods like this
}


Similar problems occur with common graph data structures. E.g. if we have nodes and edges and inherit from both of them. Now going from SubNode to SubNode won't be possible without the tricks mentioned above because of the type system.

This is a very useful feature, see Scala language docs for more info.


-- 

February 14, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1835





------- Comment #1 from andrei@metalanguage.com  2008-02-14 07:23 -------
This proposal has a lot of merit. A better example than chaining is the clone function:

class Root
{
    abstract typeof(this) clone();
    ...
}

If such a function were defined, then all derived classes would be required to implement it (which is a Good Thing) and would also be forced to return the same static type as themselves (which again is a Good Thing).

Unfortunately, this does not port nicely to functions that accept an equivariant parameter, such as opCmp and opEquals:

class Root
{
    int opCmp(typeof(this) another);
    int opEquals(typeof(this) another);
    ...
}

The intent is to have the comparison operations accept the same type as the actual static type of the object. But such a signature cannot be checked statically - a runtime check would have to be inserted.

Nonetheless, I'll bring it up with Walter.


-- 

February 14, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1835





------- Comment #2 from aarti@interia.pl  2008-02-14 08:43 -------
Well, I requested it already before... Unfortunately without much luck:

1.
http://www.digitalmars.com/d/archives/digitalmars/D/Covariance_fix_was_Idea_Lazy_upcasting_51296.html
2.
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=51201

It's also mentioned in previous bugzilla reports:
1. http://d.puremagic.com/issues/show_bug.cgi?id=323
2. http://d.puremagic.com/issues/show_bug.cgi?id=1120

The problem solution seems to have even its name: anchored types.

----------------

Additionally in current design you have to overwrite every, even simple setter/getter method in every derived class.

e.g.
class A {
  typeof(this) setX(int x) {
    this.x = x;
  }
  int x;
}

class B {
        void test() {}
}

When I don't want to redefine setX() in B, below also should work:

B b = new B;
b.setX(5).test;


-- 

February 14, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1835





------- Comment #3 from aarti@interia.pl  2008-02-14 08:47 -------
... B derives after A of course:

class A {
  typeof(this) setX(int x) {
    this.x = x;
  }
  int x;
}

class B : A {
        void test() {}
}


-- 

February 14, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1835





------- Comment #4 from andrei@metalanguage.com  2008-02-14 12:07 -------
I understand. Now the problem is that this is a feature of rather modest utility, while Walter has many much bigger rocks to move right now. I'll bring it un nonetheless.

Andrei


-- 

August 20, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1835


matti.niemenmaa+dbugzilla@iki.fi changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
OtherBugsDependingO|2295                        |
              nThis|                            |
                 CC|                            |fawzi@gmx.ch




------- Comment #5 from matti.niemenmaa+dbugzilla@iki.fi  2008-08-20 08:15 -------
*** Bug 2295 has been marked as a duplicate of this bug. ***


-- 

July 24, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=1835


Simen Kjaeraas <simen.kjaras@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |simen.kjaras@gmail.com


--- Comment #6 from Simen Kjaeraas <simen.kjaras@gmail.com> 2010-07-24 08:00:24 PDT ---
With template this parameters[1], shouldn't this bug be closed?

[1]: http://www.digitalmars.com/d/2.0/template.html#TemplateThisParameter

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
July 24, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=1835


Christian Kamm <kamm-removethis@incasoftware.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |kamm-removethis@incasoftwar
                   |                            |e.de
         Resolution|                            |FIXED


--- Comment #7 from Christian Kamm <kamm-removethis@incasoftware.de> 2010-07-24 09:15:23 PDT ---
Yes, it looks like template this parameters cover this use case. You can even express the contract of a clone function nicely:

class B {
  T clone(this T)() {
    return (cast(T)this).cloneImpl();
  }
  B cloneImpl() { return new B; }
}

class D {
  override D cloneImpl() { return new D; }
}

If the user forgets to provide cloneImpl or doesn't make it return the correct type, the compiler will complain. At least as long as clone!(D) gets instantiated somewhere.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
July 24, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=1835



--- Comment #8 from Fawzi Mohamed <fawzi@gmx.ch> 2010-07-24 16:18:40 PDT ---
Yes indeed and Christian showed this templates argument allows one workaround to achieve this (a wrapper object is another).

{{{
class A {
  void a(...){ ... }
  T aChain(this T)() {
   a();
   return cast(T)this;
  }
}
class B {
  void a(...){ ... }
}
}}}

it might even be cleaner to have also a non chainable version, the return this is really a convenience, and not strictly part of the operation itself, even if it implies some duplication.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------