#Unsure of how to correctly model

12 messages · Page 1 of 1 (latest)

rigid lintel
#

I'm trying to model the behaviour of this standard: https://www.ogc.org/standard/sfa/
I had a working version that used constructor overloading, but I really didn't like that approach, so I dectided to use static factory methods.
This change required me to make my typings a bit stricter and this is the issue I'm having now.
Most of my issues center around variations of the following error:

'T' could be instantiated with a different subtype of constraint

I think I have a decent grasp of why it doesn't work, but am unsure of how I should model this data.
To solve my second issue (type incompatibility between Polygon and CurvePolygon<LineString> I thought about adding a second generic to Geometry, but couldn't get it to work.

Thanks in advance.
Here's a playground showing my minimal production:

Overview Currently, the ISO 19125: Simple Features SWG is working to update the OGC Simple Features standards. The purpose of the ISO 19125 SWG is...

vagrant roostBOT
#
sachaw#0

Preview:ts ... export class Polygon extends CurvePolygon<LineString> ...

upper scroll
#

what's the purpose of the generics here?

empty canyon
#

You don't need the Foo<T extends Foo<T>> pattern in TS.

#

That pattern exists in other languages to solve the problem of "subclasses cannot change the signature of methods from base class" which is not a problem in TS.

upper scroll
#

it just works if you remove all the generics here

rigid lintel
#

I'll try and make my example a little more fleshed out, also What is the alternative to the Foo<T extends Foo<T>> pattern/how does TS solve it?

empty canyon
#

Let's use C# for example which requires this pattern to work.

#

The problem is as follows, take a look at this code snippet:

abstract class BaseFoo
{
    public abstract BaseFoo Clone();
}

class Foo : BaseFoo
{
    public override BaseFoo Clone() => new Foo();
    public void DoFooStuff() {}
}

new Foo().DoFooStuff();
new Foo().Clone().DoFooStuff();
//                ^^^^^^^^^^
// Does not work, Foo.Clone still returns BaseFoo

The problem is that Foo subclasses BaseFoo, but the signature of Clone cannot be changed so it still returns BaseFoo. We have to somehow pass the information of the subclass back to the base class.

#

And the way to do that is to use the Foo<T extends Foo<T>> pattern:

abstract class BaseFoo<T> where T : BaseFoo<T>
{
    public abstract T Clone();
}

class Foo : BaseFoo<Foo>
{
    public override Foo Clone() => new Foo();
    public void DoFooStuff() {}
}

Now you see the information of subclass is passed back to base class using the generic T, so now the Clone's method signature can be changed to return the subclass rather than BaseFoo.

#

However this problem simply does not exist in TS, TS allows subclass to change the method signature as long as it is still compatible with the base class:

abstract class BaseFoo {
    abstract clone(): BaseFoo
}

class Foo extends BaseFoo {
    clone() {
        return new Foo()
    }
}

const cloned = new Foo().clone()
//    ^ cloned is Foo, not BaseFoo

Foo#clone has a different signature than BaseFoo#clone, and it is allowed because Foo#clone is still fully compatible with BaseFoo#clone. So that's it, it just works, you don't need to pass information back to the base class at all.

rigid lintel
#

Great explanation, thank's for that, I definitely wen't in with the assumptions of the c# case. I'll see what I can do