Hello!

Hello!

Suppose you have a generic type such as this:

Type

TMyGeneric = class
End;

Can you declare a "class of" this thing?
Does anybody know?

Thanks :)

A

Comments

  1. What do you want to achieve?

    It you need polymorphism, you need to add the constructor constraint as well.
    TMyClass = class abstract
    constructor Create; virtual;
    end

    TMyGeneric = class
    end;

    TMyClassVariant = class(TMyClass)
    constructor Create; override;
    end;

    // defining a class of this thing :P

    TMyGenericVariant = class(TMyGeneric)
    end;

    ReplyDelete
  2. LOL!

    I want to declare a class reference type to use.
    Basically, there is an interfaced class which exposes several other interfaces.
    These are, in turn, based off a generic class and several generic descendents implementing an interface each.
    So, ideally, I would want to declare a class reference for each interface so that I could automate as much as possible in the class exposing all of the interfaces. Makes sense?

    A

    ReplyDelete
  3. TMyGeneric = class(TMyGeneric); TMyGenericClass = class of TMyGeneric;

    ReplyDelete
  4. Uh... that's not quite what I mean :)

    The basic structure is like this:

    TMyClassBase = class( TInterfacedObject )
    end;

    TMyInterface = class( TMyClassBase,IMyInterface )
    end;

    There are several of TMyInterface class types, so ideally I'd want to have one class reference for each type :)

    A

    ReplyDelete
  5. You get the answers you ask for.

    Have you tried it? What is the problem?

    ReplyDelete
  6. Basically, I have tried a few ways but no syntax I have tried seems to work; this, however, doesn't necessarily mean there isn't a way which does :)

    I am wondering if somebody's done it and how - if did.

    ReplyDelete
  7. What you are asking for, a generic meta class, is not supported in Delphi

    ReplyDelete
  8. Generics and class of don't mix unless you do it on an abstract base class, or on a final typed generic class.

    type
    TMyBase = class abstract (TInterfacedObject)
    // All the general code here needs to be unaware of any future type T
    end;

    TMyBase = class(TMyBase)
    end;

    TMyBaseFinal = class(TMyBase)
    end;

    TMyBaseClass = class of TMyBase;
    // TMyBase is compatible with TMyBaseClass
    // TMyBaseFinal is compatible with TMyBaseClass

    TMyBaseFinalClass = class of TMyBaseFinal;
    // Only takes TMyBaseFinal or descendants from it.

    Still not quite sure what you are trying to achieve and where the problem arises.

    Why not create a complete example in pastebin with less abstract class names, and demo the variations that you need, and where it actually fails and how?

    ReplyDelete
  9. Here it is.

    http://pastebin.com/W8Xcbt1L

    The idea, in other words, is to remove as much uncertainty as possible while keeping as much type-checking as possible.
    I want to be flexible, but within known bounds :)

    ReplyDelete
  10. Andrea Raimondi
    "What I would like here is to be able to have class references for all the above classes so that I can avoid having the functions as abstract and instead have them dynamic with a default implementation which takes from the referenced class types."

    Please create a explicit minimal example - because this was too much detail and not enough demonstration of WHAT you wanted.
    I don't see an immediate use for "class of" in this context? It gets really tiresome to have to guess what you actually mean.

    ReplyDelete
  11. This should be better:

    http://pastebin.com/iz6ern6S

    But I thought it was quite clear what I was trying to achieve... heh

    ReplyDelete
  12. It is quite clear what you're trying to achieve, from the first post.  David Heffernan has the right answer, though: mixing class references and generic types isn't supported.

    What Ondrej Kelle suggested would work, but if you want to keep the parameter exposed, as in your example, then there's really no way to do it.  However, if you have a concrete class to instantiate your generic with ( rather than ), you can use Ondrej's solution.

    ReplyDelete
  13. Since T is constrained to TMyClass, any concrete TMyGeneric will be compatible with TMyGeneric (TMyGeneric). Therefore TMyGenericClass from my example can refer to any concrete class TMyGeneric.

    ReplyDelete
  14. Ondrej Kelle  Not so, issues with generic type variance.

    type
    TMyClass = class
    end;

    TMyDerivedClass = class(TMyClass)
    end;

    TMyGeneric = class
    end;

    var
    obj1: TMyGeneric;
    obj2: TMyGeneric;

    begin
    obj1 := obj2;
    end.

    [dcc32 Error] Project1.dpr(18): E2010 Incompatible types: 'Project1.TMyGeneric' and 'Project1.TMyGeneric'

    In any case we are discussing meta classes.

    ReplyDelete
  15. Ondrej Kelle Have a look at http://tech.turbu-rpg.com/149/generics-and-the-covariance-problem for an explanation of why this isn't the case even though it intuitively feels like it should be.

    ReplyDelete
  16. David Heffernan
    for your example:

    type
    TMyGeneric = class(TMyGeneric);

    var
    obj1, obj2: TMyGeneric;
    obj1 := TMyGeneric(TMyGeneric.Create);
    ob2 := TMyGeneric(TMyGeneric.Create);

    ReplyDelete
  17. Ondrej Kelle​​ Naturally everything is compatible if you lie to the compiler. But so what. Still founders on covariance but now the compiler can't save you.

    And we are still talking about meta classes. Which these examples do not broach.

    ReplyDelete
  18. David Heffernan But in this case, it's not really a lie so the cast works as expected. ;-)

    ReplyDelete
  19. Ondrej Kelle​ it is a lie and it is trivial to produce runtime errors because of that lie

    ReplyDelete
  20. David Heffernan Producing runtime errors isn't too difficult, with a little determination. ;-)

    ReplyDelete

Post a Comment