参照ユニットの同名関数呼び出し切り替え

解決


北村  2013-02-08 02:57:56  No: 43792

「System」ユニットのLength関数にStringを引き渡す場合のみ
「Unit1」ユニットに新しく作成したLength関数を呼ばせたい。

string : Lehgth ⇒ Unit1.Lehgth
配列他 : Lehgth ⇒ System.Lehgth

参照ユニット(uses)でUnit1を指定した所
stringも配列他も全て「Unit1」へ参照してしまうため
引数の型がエラーとなってしまします。

上記のようなユニットを跨ったoverloadのような事は可能でしょうか?


HOta  2013-02-08 06:01:33  No: 43793

もう少し詳しく説明してください。意味がわかりません。

このような一般的な関数名をUnitの関数に使うのはやめましょう。バグのもとです。


D  2013-02-08 06:45:44  No: 43794

>string : Lehgth ⇒ Unit1.Lehgth
>配列他 : Lehgth ⇒ System.Lehgth

var
  Tmp: Integer;
  Str: String;
  Ary: array[0..2] of Integer;
begin
  //Stringの場合
  Str := 'ABC';
  Tmp := Unit1.Length(Str);

  //配列の場合
  Tmp := System.Length(Ary);

のように配列の場合、単にLengthとするのではなくSystem.Lengthとすれば良いのでは、と。

※この場合StringはUnit1.Lengthではなく単にLengthとしてもOKですが、Unit1.Lengthとした方がSystemのLengthではなくUnit1のLengthを使用していると読み取れるので良いかと。


KHE00221  2013-02-08 18:29:44  No: 43795

OVERLOAD 付けてためしたか?


KHE00221  2013-02-08 19:04:07  No: 43796

たとえば

function IntToStr(Value,Length: Integer;C: Char = '0'):String;
var
    S : String;
begin
    if Length <= 0 then
    begin
      Result := IntToStr(Value);
    end
    else
    begin
      S := StringOfChar(C,Length);
      S := S + IntToStr(Value);
      Result := Copy(S,System.Length(S)-Length+1,Length);
    end;
end;

な感じで パラメータが異なるやつならば Overload すれば可能
(SysUtils.IntToStr と共存可能)

----------

function Length(Value: String): Integer; 
begin
    Result := System.Length(Value);
end;

にしてしまうと

Stringのみで DynamicArray に対応できなくなる  (今回の話)

function Length(Value: String): Integer; overload;
begin
    Result := System.Length(Value);
end;

function Length(Value: array of Byte): Integer; overload;
begin
    Result := System.Length(Value);
end;

function Length(Value: array of Char): Integer; overload;
begin
    Result := System.Length(Value);
end;

で個別に作ると

System.Length と 同じパラメータになるでの

呼び出しがあいまいと怒られる

自作 Length のパラメータが System.Length と異なるならば
Overload すれば共存可能


Nov  2013-02-09 00:20:13  No: 43797

>自作 Length のパラメータが System.Length と異なるならば
>Overload すれば共存可能
なので、型を認識させればとりあえずはコンパイルできるようですが、String以外を一本の関数にまとめる方法は分かりません。
手間をかけてLengthを自作するより、関数名の変更を推奨します...

ちなみに、下記サンプルは、'再宣言された識別子'の警告(XE2の場合)が出ますが、
TArray<型>を手抜きせずに宣言すれば警告は消えると思います。

var
  str1: String;
  iarr: TArray<Integer>;
  farr: TArray<Double>;

function Length(S: String): SmallInt; overload;
begin
  Result := System.Length(S)*2;
end;

function Length(Arr: TArray<Integer>): SmallInt; overload;
begin
  Result := System.Length(Arr);
end;

function Length(Arr: TArray<Double>): SmallInt; overload;
begin
  Result := System.Length(Arr);
end;

begin
  str1 := 'hoge';
  SetLength(iarr, 3);
  SetLength(farr, 2);
  ShowMessage(Format('%d, %d, %d', [Length(str1), Length(iarr), Length(farr)])); // '8, 3, 2'
  SetLength(iarr, 0);
  SetLength(farr, 0);
end.


北村  2013-02-09 04:02:16  No: 43798

ご意見有難うございました。

以下の対応で場合分けする事で対応できました。
  //Stringの場合(Unit1.Length)
  Tmp := Length(Str);
  //配列の場合(System.Length)
  Tmp := System.Length(Ary);

元々Length等の共通関数にどうしても割り込みを入れなくては
ならなくなってしまったのですが
対象箇所が多すぎるために「system」から別のユニットの同名関数を参照出来ないか考えていました。
引数「String」のみ必要であったためそれ以外は「system」を参照させようと拘り過ぎていたようです。
幸い「System.」と手を入れる箇所自体少ない上、コンパイルエラーから場所特定が簡単でした。
根本解決ではありませんがベターな方法がとれそうです。

以上有難うございました。


KHE00221  2013-02-09 04:23:39  No: 43799

System.Length と 同じパラメータになるでの

呼び出しがあいまいと怒られる

これは自作Lengthも別ユニットにした場合だけだった


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加