Delphi は言語仕様として一度広げた可視性を狭めることはできません。
つまり、
typeTFoo = classpublicprocedure Test; virtual;end;TBar = class(TFoo)protectedprocedure Test; override;end;
XE3 で確認した所、可視性が低くなった事を示すヒントが出なくなっていました。
ヒントのデフォルトスイッチが変わった可能性があります。
……と思ったら、このヒントは「unit」の「interface 部」にのみ出力されるとリンク先にありました。
ヒントのデフォルトスイッチが変わった可能性があります。
……と思ったら、このヒントは「unit」の「interface 部」にのみ出力されるとリンク先にありました。
としても、Test メソッドは依然として public のままです。
そのため、クラスを継承した際に不都合がでる場合があります。
例えば、既存のライブラリクラスを継承して、新たに配布するためのクラスを作る場合などです。
自分やチームだけが使うクラスなら「このメソッドではなく、こちらを使ってください」と伝えるだけで済みます。
しかし、広範に配布するライブラリなどを作る場合では、利用者全員が利用方法を読んでくれる訳ではありません。
では、どうすれば良いかというと、使って欲しくないメソッドを Override しつつ deprecated を付けてしまえ、という事です。
deprecated 指令を付けると、コンパイラは「非推奨」という警告を出すようになります。
警告を一切気にしないユーザーには効果がありませんが、一般的なユーザーは、この警告に気づくでしょう。
具体的には以下のようにします。
typeTFoo = classpublicprocedure Test; virtual;end;TBar = class(TFoo)public// TFoo.Test を override しつつ 非推奨化procedure Test; override; deprecated 'Test2 メソッドを使って下さい';procedure Test2;end;{ TFoo }procedure TFoo.Test;beginWriteln('Hello, TFoo !');end;{ TBar }procedure TBar.Test;begininherited; // 元の TFoo.Test を呼ぶようにするend;procedure TBar.Test2;beginWriteln('Hello, TBar !');end;varBaz: TBar;beginBaz := TBar.Create;try//「W1000 シンボル 'Test' を使用することは推奨されていません」が発生する// 追加メッセージ 'Test2 メソッドを使って下さい' も表示されるBaz.Test;finallyBaz.Free;end;Readln;end.
ただし、静的メソッドの場合と final が指定されている場合は対処できません。
隠蔽で対策できる様に思いますが、下記の様に継承元の型が指定されている場合に隠蔽の効果が無くなるためです。
typeTFoo2 = classpublicprocedure Sample; // 静的メソッドend;TBar2 = class(TFoo2)public// TFoo2.Sample を隠蔽するprocedure Sample; deprecated 'Sample2 メソッドを使って下さい';procedure Sample2;end;varBaz: TFoo2; // TFoo2 型で定義するbeginBaz := TBar2.Create; // TBar2 を生成するtry// Baz の中身は TBar2 のインスタンスなのに TFoo2.Sample が呼ばれる!Baz.Sample;finallyBaz.Free;end;Readln;end.
Delphi 言語では、継承元と同じメソッド名を定義することで、継承元のメソッドを見ることができなくなります。
これを「隠蔽」と呼びます。
virtual, dynamic を隠蔽する場合 reintroduce 指令が必要です。
これを「隠蔽」と呼びます。
virtual, dynamic を隠蔽する場合 reintroduce 指令が必要です。
final 指定はまだしも、静的メソッドに deprecated を付けられないので汎用性は下がりますが、依然として有効な時もあるのでは無いでしょうか?
なお、静的メソッドや final を隠したい場合は、ラッパークラスを作る事で回避します。
小ネタでした。
0 件のコメント:
コメントを投稿