So, I’m working on some of the rendering classes for my latest project and I’ve encountered an interesting issue that I can’t explain and I’d greatly appreciate it if someone could explain to me what it is I’m doing wrong because I just can’t see it.
These are the code snippets that I believe are relevant (hopefully it’s obvious, but I’ve significantly simplified them leaving only what I think is relevant)….
unit ORE.Renderer.Classes.TextureAtlas; interface uses ORE.BaseClasses.Objects; type TTextureAtlas = class(TBaseObject) public /// <summary> /// Create a texture in the current rendering context. /// This will be the entire atlas texture. The caller is responsible /// for cleaning up the texture in OpenGL. /// </summary> function generateTextureForCurrentContext:pointer; virtual; abstract; end; TTextureAtlasClass = class of TTextureAtlas;
TBaseObject is descended from TObject and just includes some debugging/logging code I want in all my objects.
unit ORE.Renderer.OGL.TextureAtlas; interface uses ORE.Renderer.BaseClasses.TextureAtlas; type TTextureAtlasOGL = class(TTextureAtlas) public function generateTextureForCurrentContext:pointer; override; end;
unit ORE.Renderer.BaseClasses.Renderer; interface uses ORE.BaseClasses.Objects, ORE.Renderer.Classes.TextureAtlas; type TRenderer = class(TBaseObject) protected fAtlasClass: TTextureAtlasClass; end;
unit ORE.Renderer.OGL.Renderer; interface uses ORE.Renderer.BaseClasses.Renderer, ORE.Renderer.OGL.TextureAtlas; type TRendererOGL = class(TRenderer) public constructor create; end; implementation constructor TRendererOGL.create; begin inherited create; // This line... I get E2010 Incompatible types // TTextureAtlasClass <> class of TTextureAtlasOGL fAtlasClass := TTextureAtlasOGL; end;
The exact message I get is this:-
E2010 Incompatible types: ‘TTextureAtlasClass’ and ‘class of TTextureAtlasOGL’
I understand this error, but what I don’t get is how this use case is any different from that of TCollectionItem for example where the TCollection constructor expects a parameter of type TCollectionItemClass, which is defined as:-
TCollectionItemClass = class of TCollectionItem
And my collection item is TMyCollectionItem = class(TCollectionItem) and then I can create a collection like this:-
Why does this work (and I’ve included some code to test this) yet my code doesn’t? I’ve done this before and had zero issues but for some reason the compiler just doesn’t like this code.
Please help as my current work around is dirty (TTextureAtlasClass = TClass) and I’d really like to know what I’ve got wrong. I have also tried doing this by passing the class into the TRenderer constructor like TCollection but I still get this error.
All I can say is DOH!!! Notice this subtle difference…
unit ORE.Renderer.OGL.TextureAtlas; interface uses ORE.Renderer.BaseClasses.TextureAtlas;
unit ORE.Renderer.BaseClasses.Renderer; interface uses ORE.BaseClasses.Objects, ORE.Renderer.Classes.TextureAtlas;
This issue is a direct result of me changing my mind on naming conventions and source file layout.
There were two units… ORE.Renderer.BaseClasses.TextureAtlas and ORE.Renderer.Classes.TextureAtlas that both defined a class TTextureAtlas and both define a class reference type TTextureAtlasClass. TRenderer was using one whilst TRendererOGL where the error was occuring was using the other.
That will teach me for not sorting out my source files and being doubly careful when checking my code. DOH!!!