2012-05-30 169 views
2

我正在研究从商业组件套件派生的组件,并且遇到了一个我从未考虑过的挑战。请看下面的代码片段:从祖先的祖先继承方法

TMyClass = class 
protected 
    procedure SomeMethod; virtual; 
end; 

TMyClass1 = class(TMyClass) 
protected 
    procedure SomeMethod; override; 
end; 

TMyMode = (mmOne, mmTwo); 
TMyClass2 = class(TMyClass1) 
private 
    FMode: TMyMode; 
protected 
    procedure SomeMethod; override; 
public 
    property Mode: TMyMode read FMode write FMode; 
end; 

... 

procedure TMyClass2.SomeMethod; 
begin 
    if FMode = mmOne then inherited SomeMethod 
        else inherited TMyClass.SomeMethod; 
end; 

所以,如果模式= mmOne然后我继承是正常的,但如果它是mmTwo,我还是想继承我的祖先的祖先的代码,但是不知道是在祖先介绍。我已经尝试了上述,但没有成功,因为我以前从未遇到过这种情况,所以我认为这是不可能的。任何接受者?

+0

我不想成为一个煞风景,但我宁愿重新安排我的代码因此这个构造的需求消失了 - 拆分一个或两个方法,添加一个参数或其他东西。 –

+0

我同意 - 失去继承时总是存在下游问题的危险。但是,我无法控制商业组件。我可以相应地更改他们的代码,但每当我升级组件套件(DevExpress)时,都会给我带来下游维护问题。对于这个特定的场景,我认为这是最好的方法。 – Peter

回答

6

你可以用类佣工这样做:

type 
    TA = class 
    public 
    procedure X; virtual; 
    end; 

    TB = class(TA) 
    public 
    procedure X; override; 
    end; 

    TA_Helper = class helper for TA 
    procedure A_X; 
    end; 

    TC = class(TB) 
    public 
    procedure X; override; 
    end; 

procedure TA.X; 
begin 
    // ... 
end; 

procedure TB.X; 
begin 
    // ... 
end; 

procedure TA_Helper.A_X; 
begin 
    inherited X; // TA.X 
end; 

procedure TC.X; 
begin 
    A_X; 
    inherited X; // TB.X 
end; 

我觉得在D2006中存在类的帮手,但如果他们不这样做,你也可以使用一劈到一样的效果:

// ... 
    TA_Helper = class(TA) 
    procedure A_X; 
    end; 
// ... 
procedure TC.X; 
begin 
    TA_Helper(Self).A_X; 
    inherited X; // TB.X 
end; 
+0

谢谢你,hvd。这已成为世界上最好保守的秘密。你已经救了我几个小时! – Peter

4

有没有类助手或其他方法(如在@ hvd答案)这个任务的另一种解决方案。你可以得到基类方法的代码地址和self数据指针调用它:
更新的代码,没有RTTI

unit Unit4; 

interface 
type 
    TA = class(TObject) 
     protected 
     procedure Test(); virtual; 
    end; 

    TB = class(TA) 
     protected 
     procedure Test(); override; 
    end; 

    TC = class(TB) 
     public 
     procedure Test(); override; 
    end; 

implementation 

procedure TA.Test; 
begin 
    writeln('TA.Test()'); 
end; 

procedure TB.Test; 
begin 
    writeln('TB.Test'); 
end; 

procedure TC.Test; 
var TATest : procedure of object; 
begin 
    writeln('TC.Test();'); 
    writeln('call inherited TB: '); 
    inherited Test(); 


    writeln('call inherited TA:'); 
    TMethod(TATest).Data := self; 
    TMethod(TATest).Code := @TA.Test; 
    TATest(); 
end; 
end. 
+0

当然TRTTIContext在d2006中不存在,但有一个旧的rtti单元,您可以使用它来获取指向“TA.Test”方法的代码指针 – teran

+0

我不认为您可以在D2006中使用RTTI访问这些方法,所有,除非这些方法是“发布”的。 – hvd

+0

@ hvd是的,看起来像那样。但是我发现我过度使用了代码;没有必要使用RTTI(不知道D2006,但2010年工作正常)。我已经更新了答案; – teran