5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Delphi】クラスヘルパによる private メンバアクセスの件を with 文で回避できると聞いて

Last updated at Posted at 2019-08-15

はじめに

Delphi ではクラスヘルパを使うと裏技的にクラスの private メンバにアクセスできました。

最初期のクラスヘルパは Delphi のバージョン 2006 で実装されましたが、この裏技は Delphi 2009 辺りから使えるようになりました。

改悪

ところがこのクラスヘルパを使った裏技は 10.1 Berlin で封じられてしまいました。

可視性のセマンティクスを実行するため、クラス ヘルパやレコード ヘルパでは、拡張元のクラスやレコードの private メンバにはアクセスできません。

それまで使えていたものがいきなり使えなくなったため非難轟々でした。

回避策1

回避策の一つ目はインラインアセンブラで記述するというものです。

回避策2

最近見つかった回避策は With 文を使う方法です。RSP-15237 のコメ欄にこう書いてあります。

In a helper for class SomeClass with a private property SomeValue,
Self.SomeValue don't works
With Self do SomeValue :=... works
Is it a bug or something you allowed for some obscur reason ?

検証

拙作の Value Calc プロパティエディタ で検証してみます。これは IDE 用の拡張で...説明が面倒なので、詳しくは以下の動画に譲ります。

この拡張は 10.1 Berlin 対応時に、インラインアセンブラのコードを追加して問題を回避していました。

uPropEditorHelper.pas

{$IFDEF USEMULTIEXP}
function TPropertyEditorHelper.GetPropList: PInstPropList;
{$IF CompilerVersion < 31.0}
begin
  Result := Self.FPropList;
end;
{$ELSE}
// http://d.hatena.ne.jp/tales/20160420/1461081751
asm
  MOV EAX, Self.FPropList;
end;
{$IFEND}
{$ENDIF}

この部分を with 文で回避してみます。

uPropEditorHelper.pas
{$IFDEF USEMULTIEXP}
function TPropertyEditorHelper.GetPropList: PInstPropList;
begin
  with Self do
    Result := FPropList;
end;
{$ENDIF}

あら簡単。

おわりに

そのうち先述の回避策も潰されてしまうのかもしれませんが、ユーザーの意見を聞いてコンパイラ指令で使用の有無を切り替えられるようにしたらいいんじゃないかと思います。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?