How to handle Delphi Simple types when using generics?

A small example

TTest<T> = class private f : T; public function ToString : string; end; 

If this is an object then this should work

 TTest<T>.ToString; begin Result := f.ToString; end; 

But what happens when they say an integer? That would be ok in .net. sure.

I know that this will not work, but how to do it to work with objects and simple types?

+4
source share
3 answers

There are three reasons why Delphi does not allow you to do what you are trying to do in your second example - call the ToString method on a type value of type unlimited type (or at least what I thought you tried to show , since TObject.ToString is an instance method, not a class method, therefore T.ToString does not work even for TObject).

  • Delphi does not have a system with a root type, and there are very few operations that are common to all types. These operations - copying, assigning, creating locations (fields, locales, parameters, arrays) are the only operations that are guaranteed to be available for all possible values ​​of the type parameter.

  • According to 1 of them, why are operations limited to these? Why not allow operations in the generic class and give only errors during instance creation? Well, the first part of the reason is that the design was originally designed to provide maximum compatibility with .NET and dccil, so anything that prevented the use of .NET generics did not have significant advantages in developing Win32 generics.

  • A second design excuse is that instant-check-only time is problematic. The best-known implementation of parametric polymorphism using this approach is C ++ templates, and is also known for its cryptic error messages, for example, try to pass the wrong type of iterator to the algorithm and get odd complaints that overloaded operators were not found. The deeper the polymorphism, the worse the problem. This is actually so bad that C ++ itself fixes this error in the form of C ++ 0x concepts.

I hope you now understand why operations that are not guaranteed to be accessed through restrictions cannot be used. However, you can easily get rid of this limitation by providing the operation as a reference to a method or implementation of an interface, as Gamecat suggested.

In the future, Delphi generalizations for Win32 are likely to be extended by analogy with the C ++ 0x Concepts or Haskell classes, so type parameters can be limited by the presence of certain methods, functions, and operators. If he walked along the lines of a type class, then type inference can also be performed in the same way.

+7
source

The last example will not work. You need to add a restriction to use methods. In this case, TObject will be enough:

 TTest<T: TObject>.ToString; begin Result := T.ToString; end; 

You can use simple types with unlimited generics, but you are very limited in use. Since the only valid operations are assignment and comparison (equal and not equal).

In Delphi, simple types are not classes, so they have no methods. But you can do the following:

 type TToString<T> = reference to function(const AValue: T): string; TGenContainer<T> = class private FValue: T; FToString : TToString<T>; public constructor Create(const AToString: TToString<T>); function ToString: string; property Value: T read FValue write FValue; end; constructor TGenContainer<T>.Create(const AToString: TToString<T>); begin FToString := AToString; end; function TGenContainer<T>.ToString: string; begin Result := FToString(FValue); end; procedure TForm2.Button1Click(Sender: TObject); var gen : TGenContainer<Integer>; begin gen := TGenContainer<Integer>.Create( function(const AValue: Integer): string begin Result := IntToStr(AValue); end); try gen.Value := 17; Memo1.Lines.Add(gen.ToString); finally gen.Free; end; end; 

This works great.

+3
source

I suppose I could wrap my simple types in objects and override the ToString function, but that defeats the purpose of the generics.

0
source

All Articles