当前位置: 首页 > news >正文

delphi 中如何访问另一个类中到私有方法?(转载)

原始连接 http://rvelthuis.blogspot.tw/2018/01/accessing-private-methods-of-another.html

Accessing private methods of another class

 

In versions of Delphi before 10.1 Berlin, it was possible to access private members and private methods of a class simply by defining a class helper for it and accessing these private items in its methods.

But that it was so easy to access private members undermined the basic OO principles of information hiding and encapsulation. That is why this loophole (which could be considered a bug) was closed in Delphi 10.1 Berlin. But there was a lot of howling about this, because it was so easy and so convenient to have access to everything, even to other classes' "private parts".

There has been a lot of discussing going on about this. I will not repeat the arguments made there, but will state that I agree with the closing of the loophole. Accessing private members or methods is a hack, and a hack should never be easy. This hack was far too easy. Instead of using the hack, people should rather have tried to find other ways to achieve their goals.

But there is one argument of the pro-helper people that actually made sense: sometimes a class is not designed well, and you must resort to hacks.

Three hacks

They have all been mentioned before, in several blogs and StackOverflow answers, but I want to recap them here, in one post. All of these still require helper classes, as only there, you can still access private methods or members.

Accessing private methods

Say we have a class, let's call it THasPrivateMethods, that has at least one private method, let's say procedure PrivateMethod, that you want to call. The following three ways to call the private method have all been verified in Delphi 10.2.2 Tokyo. They should also work in previous versions.

Using assembler

The first way to get at private methods is to define a helper class with a new method. Here, I'll call the helper THelper and the first method CallingPrivateMethodUsingAsm. This method must be an assembler method:

type
  THelper = class helper for THasPrivateMethods
  public
    procedure CallingPrivateMethodUsingAsm;
  end;

The implementation is extremely simple:

procedure THelper.CallingPrivateMethodUsingAsm;
asm
       JMP     THasPrivateMethods.PrivateMethod
end;

In other words, in assembler, helper methods can still access private methods.

Using a method pointer

For those who are not very good with assembler, there is another, more tedious way, using a method pointer:

    procedure CallingPrivateMethodUsingTMethod; inline;

The implementation takes the address of the private method (which can apparently still be queried), puts it in a method pointer and then calls the method pointer:

type
  TPrivateMethod = procedure of object;

...
  
procedure THelper.CallingPrivateMethodUsingTMethod;
var
  M: TMethod;
begin
  M.Code := @THasPrivateMethods.PrivateMethod;
  M.Data := Self;
  TPrivateMethod(M);
end;

Using with

Inside a method of a class helper, you can't call a private method directly anymore, but you can use a simple trick (probably forgotten when they closed the loophole), using "with Self do". I am no fan of "with", but in this special case, it works as expected:

procedure THelper.CallingPrivateMethodUsingWith;
begin
  with Self do PrivateMethod;
end;

Yes, it is that easy. But you must use "with Self do" to call the private method. Now, if you inline this method, there is absolutely no overhead. It will work as if you had called the private method in your own routine:

procedure NeedsAccessToPrivateMethod;
var
  H: THasPrivateMethods;
begin
  H := THasPrivateMethods.Create;
  try
    // ...
    H.CallingPrivateMethodUsingWith;
    // ...
  finally
    H.Free;
  end;
 end;
 

Again, if CallingPrivateMethodUsingWith is inlined, the resulting code is the same as if you had written:

  try
    // ...
    H.PrivateMethod;
    // ...
  finally

If you can read assembler, you can verify this in the CPU view of the IDE.

I will discuss accessing private fields in a later post.

附录: 根据上面的思路,搞定了如何取得私有属性的值。

Tmyclass=class
    strict private i:integer;
    procedure PrivateMethod;
   public
      constructor Create ;
  end;

  TmyclassHelper = class helper for Tmyclass
  public
    procedure CallingPrivateMethodUsingAsm;
    function getp:integer;
  end;


implementation

{$R *.dfm}

{ TmyclassHelper }

procedure TmyclassHelper.CallingPrivateMethodUsingAsm;
asm
       JMP     Tmyclass.PrivateMethod;

end;

function TmyclassHelper.getp: integer;
begin
  with self do
    result:=i;

end;


{ Tmyclass }

constructor Tmyclass.Create;
begin

  i:=100;
end;

procedure Tmyclass.PrivateMethod;
begin
  showmessage('ok');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
   c:Tmyclass;

begin
  c:=Tmyclass.Create;
  c.CallingPrivateMethodUsingAsm;


  showmessage(c.getp.ToString);
end;

 



 

转载于:https://www.cnblogs.com/xalion/p/8538021.html

相关文章:

  • 1-如何自己在eclipse上配置Andriod环境
  • 十大经典排序算法
  • 【BZOJ 4449】[Neerc2015]Distance on Triangulation 多边形分治结构
  • 前端第三篇---前端基础之JavaScript
  • 线段树 Segment Tree
  • Python构造方法、析构方法和单例模式
  • 申请GV以及相关
  • java踩坑
  • hadoop第一课
  • 【PTA 天梯赛训练】电话聊天狂人(简单map)
  • 数组元素为对象,对比多个数组的相同子元素并筛选
  • SpringCloud之Hystrix断路器[六]
  • 八皇后(递归+深度优先搜索)
  • Carousel 走马灯
  • 优先队列的基本用法(java和c++)
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • 345-反转字符串中的元音字母
  • canvas 高仿 Apple Watch 表盘
  • conda常用的命令
  • Django 博客开发教程 16 - 统计文章阅读量
  • java多线程
  • js中forEach回调同异步问题
  • Laravel 实践之路: 数据库迁移与数据填充
  • opencv python Meanshift 和 Camshift
  • python学习笔记 - ThreadLocal
  • SQL 难点解决:记录的引用
  • Vue2.0 实现互斥
  • 关于List、List?、ListObject的区别
  • 警报:线上事故之CountDownLatch的威力
  • 思维导图—你不知道的JavaScript中卷
  • 用Visual Studio开发以太坊智能合约
  • 源码安装memcached和php memcache扩展
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • #QT项目实战(天气预报)
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (2)STM32单片机上位机
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (分布式缓存)Redis哨兵
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)德国人的记事本
  • (转)可以带来幸福的一本书
  • **python多态
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .bat批处理(六):替换字符串中匹配的子串
  • .bat文件调用java类的main方法
  • .jks文件(JAVA KeyStore)
  • .NET NPOI导出Excel详解
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • @private @protected @public
  • [ 网络基础篇 ] MAP 迈普交换机常用命令详解
  • [2021]Zookeeper getAcl命令未授权访问漏洞概述与解决