原始连接 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:=;
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;

delphi 中如何访问另一个类中到私有方法?(转载)的更多相关文章

  1. Java中是否可以调用一个类中的main方法?

    前几天面试的时候,被问到在Java中是否可以调用一个类中的main方法?回来测试了下,答案是可以!代码如下: main1中调用main2的主方法 package org.fiu.test; impor ...

  2. @selector 如何调用在另一个类中的静态函数?

    可以在同一个类的methodName这个函数中再调用另一个类中的静态方法

  3. Java中的一个类怎么调用另一个类中的方法

    如果另一个类中的那个方法是私有的话,就不能直接调用到,如果是其他类型的话看情况,如果是静态的(static)话,直接用类名可以调用到,如果是非静态的,就需要利用另一个类的实例(也就是用那个类生成的对象 ...

  4. C#判断一个类中有无"指定名称"的方法

    C#中可以通过反射分析元数据来解决这个问题,示例代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 2 ...

  5. 在C#中我们能调用一个类的私有方法吗

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:在C#中我们能调用一个类的私有方法吗.

  6. Java反射机制demo(五)—获得并调用一个类中的方法

    Java反射机制demo(五)—获得并调用一个类中的方法 这个demo在使用反射机制操作属性之前,主要原因是因为在.class文件字节码中,方法排在属性的前面. 1,获得一个类中的方法 先看一下方法和 ...

  7. 为什么java中只允许继承一个类?

      一个类只能继承一个其他的类 在Java语言中禁止多重继承:一个类可以具有多个直接父类.多重继承不合法的原因是容易引发意义不明确.例如,有一个类C,如果允许它同时继承A类与B类(class C ex ...

  8. pytest之将多个测试用例放在一个类中,生成唯一临时文件夹

    将多个测试用例放在一个类中 简单来说就是将多个测试用例放到类中,通过pytest去管理,这和Testng很像.示例代码如下: """ 将多个测试用例放到一个类中执行 &q ...

  9. @Transactional-同一个类中方法自调,调用方法事物失效

    问题分析 一个类中的方法调用另一个事物传播性为创建事物的方法,调用的方法事物失效? SpringAOP 代理的Service对象调用了其方法,这个方法再去调用这个Service中的其他方法是没有使用A ...

随机推荐

  1. 第二章 向量(e)起泡排序

  2. Jasper打印示例

    import java.io.IOException;import java.util.ArrayList;import java.util.HashMap;import java.util.List ...

  3. wiper

    wiper - 必应词典 美['waɪpər]英['waɪpə(r)] n.手绢儿:搌布:揩布:(汽车风挡上的)雨刷器 网络刮水器:雨刮器:拭雨器 变形复数:wipers:

  4. 游戏行业的女性拥有强大的新盟友:Facebook

    据外媒 TheNextWeb 报道,Facebook 本周宣布其新的游戏行业女性倡议,致力于鼓励更多的女性加入游戏行业.这家社交媒体公司专注于提供榜样和成功故事,而这实际上是一种令人愉快的方式.虽然游 ...

  5. cisco 割接脚本中ssh的key生成问题

    昨晚割接某企业4506更换4507过程中,运维工程师问crypto key generate rsa这个步骤是不是要单独出来进行刷配置,其实不需要的单独出来的crypto key generate r ...

  6. h5外部浏览器直接调起app

    1. 安卓端: 其中,scheme必须是小写的,同时要求H5必须是“<a href="appback://">启动应用程序</a> ” 2. h5端完整示例 ...

  7. django的request介绍和APIView流程分析和CBV的流程分析

    首先get请求的数据都在request.GET中,request.body中没有,因为只有post请求有请求体,request.body中的数据是请求体的数据 首先,我们还是用cbv的方式来讲解 我们 ...

  8. SQL Merge 语法 单表查询

    --项目中需要用到Merg语法,于是去网上查了资料,发现竟然都是多表查询,问题是我只有一张表,于是我纳闷了,后来我灵机一动,就搞定了!--表名:t_login(登录表)--字段:f_userName( ...

  9. BCH/BSV coin split troubleshooting

    BCH/BSV coin split troubleshootingMark Lundeberg 2018 November 27ResourcesGuides:Locktime based spli ...

  10. linux C程序中获取shell脚本输出(如获取system命令输出)

    转载自 http://blog.csdn.net/hjxhjh/article/details/7909518 1. 前言 Unix 界有一句名言:“一行shell脚本胜过万行C程序”,虽然这句话有些 ...