Delphi 跨单元进入(访问)类的私有成员,protected ,private部分



作者:二娃


 


delphi 中,同单元类,可以任意进入类成员的private至pulished部分,没有任何限制,但是对于不同的单元之间,如何进入protected ,private部分访问呢?


 


我先讲讲进入protected部分:


进入protected相对简单,现举个例子:


type


TCustomForm = class(TScrollingWinControl)


protected


FFormState: TFormState;


public


property FormState: TFormState read FFormState;


end;


TForm = class(TCustomForm);


从上面可以看出 TForm 的属性FormState是一个只读属性,正常情况下,是不能直接改变这个属性值的.但是我们可以通过一个以下来访问:


新申明一个类,这个类什么事也不做


type


TFormAccess = class(TForm);


 


procedure TForm1.Button1Click(Sender: TObject);


begin 


//这样我们就可以访问FFormState并且可以改变其值


Include(TFormAccess(Form1).FFormState, fsCreating); //注意是TFormAccess 而不是TForm


end;


 


对于private内成员跨单元相对复杂一些:


在这里我借用网上的一个贴子,上面有详细的介绍:




上面的方法相对很繁琐,delphi没搞几年可能看不明白,借用《亮剑》上李云龙的句名言:云山雾绕的,那好,在这里,我介绍一种更为简单的方法,这也是我多年经验的总结


比如:


TList = class(TObject)


private


FList: PPointerList;


FCount: Integer;


FCapacity: Integer;


protected


function Get(Index: Integer): Pointer;


procedure Grow; virtual;


procedure Put(Index: Integer; Item: Pointer);


procedure Notify(Ptr: Pointer; Action: TListNotification); virtual;


procedure SetCapacity(NewCapacity: Integer);


procedure SetCount(NewCount: Integer);


public


destructor Destroy; override;


function Add(Item: Pointer): Integer;


procedure Clear; virtual;


procedure Delete(Index: Integer);


class procedure Error(const Msg: string; Data: Integer); overload; virtual;


class procedure Error(Msg: PResStringRec; Data: Integer); overload;


procedure Exchange(Index1, Index2: Integer);


function Expand: TList;


function Extract(Item: Pointer): Pointer;


function First: Pointer;


function GetEnumerator: TListEnumerator;


function IndexOf(Item: Pointer): Integer;


procedure Insert(Index: Integer; Item: Pointer);


function Last: Pointer;


procedure Move(CurIndex, NewIndex: Integer);


function Remove(Item: Pointer): Integer;


procedure Pack;


procedure Sort(Compare: TListSortCompare);


procedure Assign(ListA: TList; AOperator: TListAssignOp = laCopy; ListB: TList = nil);


property Capacity: Integer read FCapacity write SetCapacity;


property Count: Integer read FCount write SetCount;


property Items[Index: Integer]: Pointer read Get write Put; default;


property List: PPointerList read FList;


end;


对于TList的 private成员


FList: PPointerList;


FCount: Integer;


FCapacity: Integer;


这三个成员,可以通过下面方式访问


 


先声明一个类,


//注意这里,跟TList继承自同一个类.这是关键,这样保证这个新类与TList在vmt表的地址顺序是一样的


TListAccess = class(TObject)


public //注意:FList前面加一个public,还要特别注意的是,下面三个成员必需与原TList的顺序一致,否/则访问时地址会出错


FList: PPointerList;


FCount: Integer;


FCapacity: Integer;


end;


然后,我们直接这样访问了


TListAccess(List1).FList


TListAccess(List1).FCount


TListAccess(List1).FCapacity


看到没有,可以做任何事了,哈哈,够简单吧?


最后要注意的是,对于新手来说,如果你对delphi的vcl机制不熟悉,最好不要控制vcl控件的私有成员,那样风险很大的