原始连接 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. centos 7 下 Ceph 配置安装

    一.环境介绍 系统: CentOS Linux release 7.3.1611 (Core) 硬盘: 系统盘:300GB*2-raid 1 OSD:600GB*4-raid 5      ceph ...

  2. unity3d英语单词拼写小游戏Pics Quiz Maker With Categories 3.0

    下载地址: https://item.taobao.com/item.htm?spm=0.7095261.0.0.19f71debcef4hT&id=575991216080

  3. javascript实现留言功能

    原理: 1.用户在留言框输入留言 2.利用textarea的value属性获取到用户输入的留言 3.动态创建一个li 4.将获取的留言打包成html存到li中 5.根据需要添加删除留言.统计留言数量等 ...

  4. 对于装office 365时,visio不兼容的解决

    先将office 365装好,之后从这个网址下载visio安装即可,但是没有 激活码,需要自己激活: 网址:链接: https://pan.baidu.com/s/1OqONPuJ0eumrpts-X ...

  5. queue模拟

    BlockingQueue:顾名思义,首先它是一个队列,并且支持阻塞的机制,阻塞的放入和得到数据.我们要实现LinkedBlockingQueue下面两个简单的方法put和take. put(anOb ...

  6. Linux 下 mysql的基本配置

    Linux 下 mysql的基本配置 2013年02月27日 ⁄ MySQL ⁄ 共 3000字 ⁄ 暂无评论 ⁄ 被围观 2,483 views+ 1. Linux mysql安装:    $ yu ...

  7. java 向上转型和向下转型

    学习向上转型和向下转型怎么用没多难,但是为什么那样用,我搞了很多次没弄明白.没弄明白的原因是平时学习时之看例子,而例子一般都比较简单,没有对象之间的调用,一般就是一个对象调用自己的方法. 首先看下怎么 ...

  8. opencv 双边模糊,膨胀腐蚀 开 闭操作

    #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; int main(int argc, ...

  9. C#—Dev XtraTabControl操作总结如动态增加Tab和关闭选项卡方法等

    1:显示行号 找到gridview属性 点击事件 CustomDrawRowIndicator private void gridView1_CustomDrawRowIndicator(object ...

  10. Oracle_高级功能(3) synonym和database link

    一.同义词synonymconnect sys/123 as sysdba;select * from emp;ORA-00942: 表或视图不存在create synonym emp for sco ...