About the author
Lutz Roeder originally wrote Digger in C# many years ago. In 2004, I ported it first to Delphi.NET, and then to Delphi for Win32. In February 2009, I ported it to the Android platform.
Today, I'll discuss a pattern that I worked on when porting C# to Delphi.
In Digger's C# code, the following code sequence is seen.
Type[] t = { typeof(Nothing), typeof(Stone), typeof(Ground), typeof(Ghost180), null, typeof(Diamond), typeof(Wall), typeof(Ghost90L), null, typeof(UvStone), typeof(Digger), typeof(Ghost90LR), typeof(Exit), null, typeof(Changer), typeof(Ghost90R) }; SetSprite(x, y, (Sprite) Activator.CreateInstance(t[id]));
Type[] t = { typeof(Nothing), typeof(Stone), typeof(Ground), typeof(Ghost180), null, typeof(Diamond), typeof(Wall), typeof(Ghost90L), null, typeof(UvStone), typeof(Digger), typeof(Ghost90LR), typeof(Exit), null, typeof(Changer), typeof(Ghost90R) };
MSDN explains typeof as such: "The typeof operator is used to obtain the System.Type object for a type". The intention of the above code is to create an instance of a Sprite descendent, depending on the id given.
When translating C# to Delphi, I used the Class-Reference (or metaclass) pattern. The code sequence was translated as such in Delphi (both .NET and the Win32 target):
type SpriteClass = class of Sprite; const t: array[0..15] of SpriteClass = ( SpriteNothing, SpriteStone, SpriteGround, SpriteGhost180, nil, SpriteDiamond, SpriteWall, SpriteGhost90L, nil, SpriteUvStone, SpriteDigger, SpriteGhost90LR, SpriteExit, nil, SpriteChanger, SpriteGhost90R); var ASprite: Sprite; begin ASprite := t[id].Create; SetSprite(x, y, ASprite); end;
In the parent Sprite class, I declared a virtual constructor, and in each of the Delphi classes, I had to override the virtual constructor.
For the Android port, when translating Delphi to Java, I used the class literals pattern.
final Class<?>[] t = { Nothing.class, Stone.class, Ground.class, Ghost180.class, null, Diamond.class, Wall.class, Ghost90L.class, null, UvStone.class, Digger.class, Ghost90LR.class, Exit.class, null, Changer.class, Ghost90R.class };Class<?> c = t[id];if (c!=null) SetSprite(x, y, (Sprite) c.newInstance());
In each of the descendent Java classes, I did not provide any constructors, since by default, Java has a rule such that "The compiler automatically provides a no-argument, default constructor for any class without constructors."
So there you go! A way of creating an instance of a class in 3 different languages!
Link to the Android application Link to the Digger Delphi Windows application
How to free more space on your home drive by redirecting the location for SDKs in RAD Studio
Learn the command line used to compile System.pas in Delphi
A method to design records so that they're allocated on a specific byte boundary, such as 16 bytes, 512 bytes, 4096 bytes, etc.
Learn why the map is cool in Go!