# 【Delphi】クラスヘルパによる private メンバアクセスの件を with 文で回避できると聞いて --- tags: Delphi programming embarcadero objectpascal created_at: 2019-08-15 updated_at: 2019-08-15 --- # はじめに Delphi ではクラスヘルパを使うと裏技的にクラスの private メンバにアクセスできました。 最初期のクラスヘルパは Delphi のバージョン 2006 で実装されましたが、この裏技は Delphi 2009 辺りから使えるようになりました。 - [クラス ヘルパとレコード ヘルパ(Delphi)(DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E3%82%AF%E3%83%A9%E3%82%B9_%E3%83%98%E3%83%AB%E3%83%91%E3%81%A8%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89_%E3%83%98%E3%83%AB%E3%83%91%EF%BC%88Delphi%EF%BC%89) - [クラスヘルパ (Owl's perspective)](http://owlsperspective.blogspot.com/2011/11/class-helper.html) # 改悪 ところがこのクラスヘルパを使った裏技は 10.1 Berlin で封じられてしまいました。 > 可視性のセマンティクスを実行するため、クラス ヘルパやレコード ヘルパでは、拡張元のクラスやレコードの private メンバにはアクセスできません。 - [15.3 Delphi コンパイラのその他の改良点 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/Berlin/ja/%E6%96%B0%E6%A9%9F%E8%83%BD#Delphi_.E3.82.B3.E3.83.B3.E3.83.91.E3.82.A4.E3.83.A9.E3.81.AE.E3.81.9D.E3.81.AE.E4.BB.96.E3.81.AE.E6.94.B9.E8.89.AF.E7.82.B9) **それまで使えていたものがいきなり使えなくなったため非難轟々でした。** ## 回避策1 回避策の一つ目はインラインアセンブラで記述するというものです。 - [10.1 Berlinのclass helper仕様変更は全然改良じゃないと思った? (Swanman's Horizon / 全力わはー)](https://lyna.hateblo.jp/entry/20160420/1461081751) ## 回避策2 最近見つかった回避策は **With** 文を使う方法です。[RSP-15237](https://quality.embarcadero.com/browse/RSP-15273) のコメ欄にこう書いてあります。 > 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 ? - [RSP-15237 Add possibility to access to private properties and methods in natural way like it was for class helpers (Quality Potal)](https://quality.embarcadero.com/browse/RSP-15273) ## 検証 拙作の [Value Calc プロパティエディタ](https://ht-deko.com/delphiforum/?vasthtmlaction=viewtopic&t=1349) で検証してみます。これは IDE 用の拡張で...説明が面倒なので、詳しくは以下の動画に譲ります。 - http://www.youtube.com/watch?v=YSoVQT1vaEM - http://www.youtube.com/watch?v=5qu7MQ3PwZE - http://www.youtube.com/watch?v=Pv-J3gJ4IXQ - http://www.youtube.com/watch?v=1YgdT03elYs この拡張は 10.1 Berlin 対応時に、インラインアセンブラのコードを追加して問題を回避していました。 ```pascal: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** 文で回避してみます。 ```pascal:uPropEditorHelper.pas {$IFDEF USEMULTIEXP} function TPropertyEditorHelper.GetPropList: PInstPropList; begin with Self do Result := FPropList; end; {$ENDIF} ``` あら簡単。 # おわりに そのうち先述の回避策も潰されてしまうのかもしれませんが、ユーザーの意見を聞いてコンパイラ指令で使用の有無を切り替えられるようにしたらいいんじゃないかと思います。