Code Monkey home page Code Monkey logo

Comments (10)

theJenix avatar theJenix commented on July 18, 2024

What is the right way to declare and reference static members inside classes with type parameters? For example, I have a class and I'm implementing a Null object for that class:

class MyClass<T> {
    public static final Null = new MyClass<T>();
}

If I instantiate a MyClass<String> I cannot compare it with MyClass.Null:


var myStr = new MyClass<String>();
if (myStr == MyClass.Null) { // this line gives an error

}

from haxe.org-comments.

ibilon avatar ibilon commented on July 18, 2024

@theJenix The type parameter only exists for the instance fields, you can see static fields as global variables created before the main function is run, they can't use the type parameter because they are "outside the class".

from haxe.org-comments.

Simn avatar Simn commented on July 18, 2024

Uhm, that shouldn't even compile...

from haxe.org-comments.

theJenix avatar theJenix commented on July 18, 2024

Thanks @ibilon and @Simn! For what it's worth, this is an intersection of two very common language patterns, e.g. parametrized types and the Null Object pattern. It would be nice if the docs had some discussion about what the "right" way to achieve this is, as it's very possible in other similar languages.

For example, I made this work for me by declaring Null as an instance variable (not static); that feels a little heavy because now every MyClass will have the overhead of it's own Null object. Is that the recommended "right way" do implement this in Haxe? Or is there another, cleaner way to do this?

from haxe.org-comments.

Simn avatar Simn commented on July 18, 2024

The concept of a null-value for a parameterized type seems dubious to me. You can always just initialize it to new MyClass() without specifying the type parameter, but then you'll end up with MyClass<Unknown> and that will unify with the first type it is assigned to/from. If you want it to unify with everything then you'll likely want MyClass<Dynamic>.

Could you give an example of another language that supports this? I'd like to understand the semantics you're after because this could involve anything from bottom types to existential type parameters.

from haxe.org-comments.

theJenix avatar theJenix commented on July 18, 2024

Sure. The first one that comes to mind is C#:

    class MyClass<T> {
        public static MyClass<T> Null = new MyClass<T>();

        public MyClass<T> get() {
            return MyClass<T>.Null;
        }
    }

    class Test {
        bool testMe() {
            return new MyClass<string>().get() == MyClass<string>.Null;
        }
    }

In this case, T is accessible by static items as part of the class; in fact, in get() I can just return Null instead of qualifying it with the class name and it still compiles. I think this means that Null is static across all MyClass (for a specific value of T), and not globally static, but this is still probably preferable to a Null per instance.

Typescript also supports a version of this:


class MyClass<T> {
    static Null = new MyClass()

    get():MyClass<T> {
        return MyClass.Null;
    }
}

function testMe() {
    return new MyClass<number>().get() === MyClass.Null && new MyClass<string>().get() === MyClass.Null
}

In this case, new MyClass() actually does end up at MyClass but that seems to suffice for being able to return the null object from get() and it satisfies a strict === test.

As some added context, the reason I am exploring this pattern in the first place is while normally I appreciate the struct null safety in Haxe, sometimes it can be a little too aggressive so in some cases. Rather than deal with it, sometimes it makes sense to just not use null and instead use a null object but maybe improving the null safety checker would be a better overall experience here?

from haxe.org-comments.

Simn avatar Simn commented on July 18, 2024

In the case of C# this makes some sense because it has real generics, so something similar to Haxe's @:generic.

The Typescript version looks like it would just be MyClass<Dynamic> in Haxe, though I wonder how their typing works for cases like this. Basically, what is the type of MyClass.Null itself, without any other operations? I suspect that they treat its type parameter like an any-type.

from haxe.org-comments.

theJenix avatar theJenix commented on July 18, 2024

This is what the Typescript plugin in VS Code reports:
image.

Which I think tracks with what you're saying re MyClass. I could change the typescript code to new MyClass<never>() or new MyClass<any>() or even new MyClass<string>() and it still functions as described above; I'm guessing the type param is ignored when used in this way.

Incidentally, I was checking thru some older code of mine and it looks like I had previously implemented this pattern by declaring Null to be of type Dynamic (not MyClass<Dynamic>). If I try using MyClass<Dynamic> for the type of Null in this case, the compiler complains when I then try and pass Null in for a concrete type, e.g. MyClass<MyOtherClass>. I'm guessing because "Dynamic" is not factored in when checking for invariance.

Ultimately, the goal here is to have a single object that can represent null and possibly stand in for the the "real object" to write code that is free of null reference exceptions, so declaring a Null variable of type Dynamic and then ensuring that it is populated with the correct type of object isn't bad. If I could declare it as MyClass<Dynamic> for that added bit of type safety, that would be better.

Also, I tried experimenting with @:generic but it looks like we can't have static fields inside a generic type; making that work could maybe also be a workable solution here, letting me decide if I really want a type safe static object inside a parameterized type.

In either case, I think it would be helpful to add a note on this page talking about this and/or similar use cases, or at least acknowledging that this concept is not supported. There's a Trivia note that talks about why we cannot use angle brackets in expressions; maybe something on the level of that?

from haxe.org-comments.

cardgdev avatar cardgdev commented on July 18, 2024

Regarding the trivia section at the end "...why a method with type parameters cannot be called as method<String>(x) ...", is there no other way to supply the method generic parameter like this, other than passing in an object and letting it be implicitly inferenced?

Something like:

    var data: Dynamic;
    function getDataLike<T>(): T {
        return cast data;
    }

    var view = getDataLike<{myInfoView: String}>();

from haxe.org-comments.

kLabz avatar kLabz commented on July 18, 2024

var view:{myInfoView: String} = getDataLike(); would work for this example

from haxe.org-comments.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.