Os tipos primitivos têm regras de conversão padrão, muitas linguagens de programação funcionam dessa forma por padrão. Isto é para que você não tenha que digitar tudo e é realmente uma conveniência. Por exemplo, você será capaz de atribuir um Integer a um Extended sem problemas, tanto passando um 42 literal como atribuindo uma variável do tipo Integer.
procedure Hello; var SomeNumber: Extended; AnotherNumber: Integer; begin AnotherNumber := 6; SomeNumber := 2; // works SomeNumber := AnotherNumber; // works end;
Mesmo que digitem aliasing, os tipos ainda são os tipos que eram e têm regras de conversão automática:
type ANewType = Extended; AnotherNewType = Integer; implementation procedure Hello; var SomeNumber: ANewType; AnotherNumber: AnotherNewType; begin AnotherNumber := 6; SomeNumber := 2; // works SomeNumber := AnotherNumber; // works end;
Se você realmente quer regras de conversão rigorosas, porque, por exemplo, você quer evitar que os medidores sejam atribuídos a segundos ou vice-versa, você precisará criar novos tipos. E novos tipos são criados usando ou um registro ou uma classe.
Para permitir certas conversões, você pode adicionar essas regras aos tipos utilizando a sobrecarga do operador. (veja https://docwiki.embarcadero.com/RADStudio/Sydney/en/Operator_Overloading_(Delphi))
No FPC a sintaxe é diferente, mas você pode fazer o mesmo https://www.freepascal.org/docs-html/ref/refse104.html#x224-24800015.3
Você pode até mesmo fazer regras de conversão para metros * segundos criando um tipo de metro por segundo.
Aqui está um exemplo de como funciona em Delphi:
type metersPerSecond = record private m: Extended; s: Extended; value: extended; mset: Boolean; sset: Boolean; function Units: string; public function ToString: string; end; meters = record private value: Extended; function Units: string; public class operator Implicit(Value: Extended): meters; class operator Explicit(Value: meters): metersPerSecond; class operator Multiply(ms: metersPerSecond; m: meters): metersPerSecond; function ToString: string; end; seconds = record private value: Extended; function Units: string; public class operator Implicit(Value: Extended): seconds; class operator Explicit(Value: seconds): metersPerSecond; class operator Multiply(ms: metersPerSecond; s: seconds): metersPerSecond; function ToString: string; end; implementation uses SysUtils; class operator meters.Implicit(Value: Extended): meters; begin Result.value := Value; end; class operator seconds.Implicit(Value: Extended): seconds; begin Result.value := Value; end; class operator meters.Explicit(Value: meters): metersPerSecond; begin Result.m := Value.value; Result.mset := True; if Result.sset then Result.value := Result.s * Result.m; end; class operator seconds.Explicit(Value: seconds): metersPerSecond; begin Result.s := Value.value; Result.sset := True; if Result.mset then Result.value := Result.s * Result.m; end; class operator seconds.Multiply(ms: metersPerSecond; s: seconds): metersPerSecond; begin Result := ms; Result.s := s.value; Result.sset := True; if Result.mset then Result.value := Result.s * Result.m; end; class operator meters.Multiply(ms: metersPerSecond; m: meters): metersPerSecond; begin Result := ms; Result.m := m.value; Result.mset := True; if Result.sset then Result.value := Result.s * Result.m; end; function metersPerSecond.Units: string; begin Result := 'm/s'; end; function metersPerSecond.ToString: string; begin Assert(mset and sset); Result := Format('%f%s', [value, Units]) end; function meters.Units: string; begin Result := 'm'; end; function meters.ToString: string; begin Result := Format('%f%s', [value, Units]); end; function seconds.Units: string; begin Result := 's'; end; function seconds.ToString: string; begin Result := Format('%f%s', [value, Units]); end; var time: seconds; distance: meters; speed: metersPerSecond; different_speed: metersPerSecond; initialization time := 10.0; distance := 3; // distance := meters; // does not work, because seconds are not meters! speed := metersPerSecond(time) * distance; // or the other way around speed := metersPerSecond(distance) * time; WriteLn('speed -> ' + time.ToString + ' * ' + distance.ToString + ' = ' + Speed.ToString); // different_speed := distance; // this doesn't work without explicit conversion WriteLn('different_speed -> ' + different_speed.ToString); end.
Contato