gpt4 book ai didi

delphi - 防止类型转换可以揭示隐藏的属性?

转载 作者:行者123 更新时间:2023-12-03 18:56:22 28 4
gpt4 key购买 nike

此问题与我问的先前问题有关:How do I prevent access to the Items property in TCustomListView?

我在上面链接的问题中张贴了我的答案。基本上,我欺骗了我的TMyCustomListView派生组件,使其使用另一个受保护的Items类,因此在设计时或运行时不可见或不可访问。

我发现了一个缺点,尽管如此,您仍然可以对它进行类型转换,以显示原始的listview Items属性。

TListView(MyListView1).Items.Add.Caption := 'test';

我认为我组件的任何潜在用户都不大可能知道该组件是从TMyCustomListView派生的,以及他们是否需要将其转换为列表视图。但是由于我完全不希望访问原始listview Items属性,因为用户无论如何都不需要访问它,因此我对此问题的最新疑问是是否有可能阻止我的组件停止运行。打字?

谢谢。

最佳答案

简短答案

继承的全部要点是子类必须看起来像其祖先。您只能添加功能,而不能删除它。

因此,没有人不能做您想做的事情。

但是,只需做一些工作,就可以实现合适的封装效果。您需要使用合成而不是继承。 (建议:对“偏爱组成而不是继承”进行一些研究。)



长答案

如果标准列表视图功能对组件的用户没有用,那么您就不能说组件是列表视图。 is-a关系正是继承所代表的。

使用对象时,基本上有2种方法可以重用代码:


从其他类继承:它提供祖先类中的所有功能。 (强调所有,因为您甚至获得了不需要的功能。)
使用其他对象:您拥有对另一个对象的引用并要求它为您工作。


因此,与其从列表视图继承,不如考虑使用组合。该方法非常类似于您在其他问题中的回答,只需更改您继承的祖先即可。

TMyCustomListView = class(TComponent)
private
FListView: TListView;
public
constructor Create(AOwner: TComponent); override;
end;

constructor TMyCustomListView .Create(AOwner: TComponent); override;
begin
inherited Create(AOwner);
FListView := TListView.Create(Self);
end;


当然,您会找到希望列表视图支持的一大堆功能,这些功能已经被 TListView支持。您想要公开的任何此类功能,只需将其重定向到内部列表视图即可。例如。

procedure TMyCustomListView.AddItem(Item: String; AObject: TObject);
begin
FListView.AddItem(Item, AObject);
end;


事实证明,由于不再继承,因此不希望支持列表视图的界面。因此,您现在可以自由地进行更改,使其更适合您的组件。

procedure TMyCustomListView.AddItem(AItemCaption: String;
AObject: TMySpecialListViewObject; AItemHint: String);
begin
//By forcing a specific kind of object to be added to your list view,
//you know that anything added will be of an appropriate type.
//Meaning that you can rely on using TMySpecialListViewObject
//attributes in other places in your component.

FListView.AddItem(Item, AObject);

//Of course you can also do other things before or after adding to
//the internal list view.
end;


利弊

是的,很明显,使用组合而不是继承需要做更多的工作:


您不会自动获得内部对象的功能。
您必须显式添加所需的内容,将调用重定向到内部对象。
您可能需要拦截事件以跟踪内部对象发生了什么。
如果您的内部对象没有提供您所需要的一切,则某些事情可能很难支持。 (对于VCL类尤其如此,其中许多类共享同一单元,并且可以像“朋友”类一样访问私有成员。)


但是优点是:


与第2点一样,缺点:您必须显式添加所需的内容。但是在这种情况下,意味着您不会坐在自己不想要的东西上。
更好的封装。
您的类更易于使用,因为它具有较少的方法/属性供用户理解。
从长远来看,您的代码将更具可维护性,因为您不必担心有人“不正确地”使用您的类。
您的类倾向于“轻量级”,因为它们不会因未使用的功能而肿。
轻量级课程更易于测试。


这些优点基本上就是为什么“继承优先于构图”被认为是一种好的设计实践的原因。

但是就像软件开发中的所有事情一样:您必须权衡利弊,并选择每种情况下最合适的。有时,即使一种类型确实应该从另一种类型继承,您也可以选择继续这样做。

旁注

在示例中,我演示了从 TComponent继承。但是,如果要允许其他人以 TWinControlTControl与您的组件进行交互,则必须相应地更改继承。

如果从 TWinControl继承,则需要确定将哪些win控制功能重定向到内部列表视图,以及最合适的方法。

例如。您可以覆盖 CreateWindowHandle来简单地将您的句柄设置为内部列表视图的句柄。否则,您可能会进行全面的消息处理,并决定将哪些消息传递给内部对象。

我将在这里不做更多详细介绍,因为这个答案已经足够长了。

关于delphi - 防止类型转换可以揭示隐藏的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24519377/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com