Thread overview
How do you return a subclass instance from a base class method?
Nov 17
zjh
November 17

I have SubclassOf derived from PosetRelation. For any poset relation, the transitivity law applies, however, I'd like to return the correct type:

   PosetRelation transitivity(PosetRelation R, PosetRelation S)
   {
      if (R.op == S.op)
      {
         if (R.right is S.left)
            return new SubclassOf(R.left, S.right);
      }

      return null;
   }

How does one accomplish this in D? Because PosetRelation doesn't know about SubclassOf, in general.

November 17

On Thursday, 17 November 2022 at 04:25:13 UTC, Daniel Donnelly, Jr. wrote:

>

I have SubclassOf derived from PosetRelation. For any poset relation, the transitivity law applies, however, I'd like to return the correct type:

How does one accomplish this in D? Because PosetRelation doesn't know about SubclassOf, in general.

You can use TypeInfoClass:

class Base
{
}

class Derived : Base
{
}

Object newDerivedFromTi(Base b)
{
    return typeid(b).create();
}

void main(string[] args)
{
    Base b = new Base;
    Base d = new Derived;
    assert(cast(Derived)newDerivedFromTi(d));
}

But that only works with default constructors, i.e no parameters.
Another way is to define a virtual function in the Base:

class Base
{
    Object createMostDerived(Base b1, Base b2)
    {
        return new typeof(this);
    }
}

class Derived : Base
{
    override Object createMostDerived(Base b1, Base b2)
    {
        return new typeof(this);
    }
}

Object newDerivedFromTi(Base b)
{
    return b.createMostDerived(b, b);
}

void main(string[] args)
{
    Base b = new Base;
    Base d = new Derived;
    assert(cast(Derived)newDerivedFromTi(d));
}

assuming the PosetRelation (here called Base) actually cary the SubclassOf type (here called Derived).

November 17
PosetRelation transitivity(PosetRelation R, PosetRelation S)
{
   // These if conditions are typically ordered from easiest to
   // most involved-to-check.
   if (R.op == S.op &&
       is(typeof(R) == typeof(S)) &&
       R.right == S.left)
   {
      return new typeof(R)(
         R.left, S.right,
         by("transitivity of " ~ R.op));     // Proof by this axiom
   }

   return null;
}

Not sure if that would work yet. Have to test it.

November 17

On Thursday, 17 November 2022 at 04:25:13 UTC, Daniel Donnelly, Jr. wrote:

>

...

crtp, will it work?

November 17

On Thursday, 17 November 2022 at 05:34:49 UTC, zjh wrote:

>

On Thursday, 17 November 2022 at 04:25:13 UTC, Daniel Donnelly, Jr. wrote:

>

...

crtp, will it work?

Can't use CRTP, because once you choose a derived class to pass into the template system, how do you pass in subclasses of that class and so on...

November 17

On Thursday, 17 November 2022 at 05:21:05 UTC, MorteFeuille123 wrote:

>

On Thursday, 17 November 2022 at 04:25:13 UTC, Daniel Donnelly, Jr. wrote:

>

[...]

You can use TypeInfoClass:

[...]

I don't get it - you never made use of b1 or b2...

November 17

On Thursday, 17 November 2022 at 06:48:13 UTC, Daniel Donnelly, Jr. wrote:

>

On Thursday, 17 November 2022 at 05:21:05 UTC, MorteFeuille123 wrote:

>

On Thursday, 17 November 2022 at 04:25:13 UTC, Daniel Donnelly, Jr. wrote:

>

[...]

You can use TypeInfoClass:

[...]

I don't get it - you never made use of b1 or b2...

yeah this was oversimplified on purpose, I did not realize that this coulmd be confusing. I dont know what you do with your constructor parameter either, would I say, as a second explanation.

November 17

On 11/16/22 11:25 PM, Daniel Donnelly wrote:

>

I have SubclassOf derived from PosetRelation.  For any poset relation, the transitivity law applies, however, I'd like to return the correct type:

    PosetRelation transitivity(PosetRelation R, PosetRelation S)
    {
       if (R.op == S.op)
       {
          if (R.right is S.left)
             return new SubclassOf(R.left, S.right);
       }

       return null;
    }

How does one accomplish this in D?  Because PosetRelation doesn't know about SubclassOf, in general.

I'd use a template:

T transitivity(T : PosetRelation)(T R, T S)
{
      if (R.op == S.op)
      {
         if (R.right is S.left)
            return new T(R.left, S.right);
      }

      return null;
}

-Steve