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
Suppose you have a generic type such as this:
Type
TMyGeneric
End;
Can you declare a "class of" this thing?
Does anybody know?
Thanks :)
A
What do you want to achieve?
ReplyDeleteIt 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;
LOL!
ReplyDeleteI 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
TMyGeneric = class(TMyGeneric); TMyGenericClass = class of TMyGeneric;
ReplyDeleteUh... that's not quite what I mean :)
ReplyDeleteThe 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
You get the answers you ask for.
ReplyDeleteHave you tried it? What is the problem?
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 :)
ReplyDeleteI am wondering if somebody's done it and how - if did.
What I've shown works.
ReplyDeleteWhat you are asking for, a generic meta class, is not supported in Delphi
ReplyDeleteGenerics and class of don't mix unless you do it on an abstract base class, or on a final typed generic class.
ReplyDeletetype
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?
Here it is.
ReplyDeletehttp://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 :)
Andrea Raimondi
ReplyDelete"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.
This should be better:
ReplyDeletehttp://pastebin.com/iz6ern6S
But I thought it was quite clear what I was trying to achieve... heh
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.
ReplyDeleteWhat 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.
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.
ReplyDeleteOndrej Kelle Not so, issues with generic type variance.
ReplyDeletetype
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.
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.
ReplyDeleteDavid Heffernan
ReplyDeletefor your example:
type
TMyGeneric = class(TMyGeneric);
var
obj1, obj2: TMyGeneric;
obj1 := TMyGeneric(TMyGeneric.Create);
ob2 := TMyGeneric(TMyGeneric.Create);
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.
ReplyDeleteAnd we are still talking about meta classes. Which these examples do not broach.
David Heffernan But in this case, it's not really a lie so the cast works as expected. ;-)
ReplyDeleteOndrej Kelle it is a lie and it is trivial to produce runtime errors because of that lie
ReplyDeleteDavid Heffernan Producing runtime errors isn't too difficult, with a little determination. ;-)
ReplyDelete