Ben*_*boy 4 delphi tfilestream tstream
我有一个继承自TFileStream的类和一个继承自TMemoryStream的类.两者都实现与读取数据完全相同的功能,例如:
TCustomFileStream = class (TFileStream)
function ReadByte: byte;
function ReadWord: word;
function ReadWordBE: word;
function ReadDWord: longword;
function ReadDWordBE: longword;
function ReadString(Length: integer): string;
function ReadBlockName: string;
etc
Run Code Online (Sandbox Code Playgroud)
当我想编写一个可以将任何类型的流作为参数的函数时,我必须使用TStream:
function DoStuff(SourceStream: TStream);
Run Code Online (Sandbox Code Playgroud)
这当然意味着我无法使用自定义功能.什么是解决这个问题的最好方法?理想情况下,我希望能够有一个兼容FileStream或MemoryStream的Tstream兼容类,所以我可以做这样的事情,如果流是FileStream或MemoryStream则无关紧要:
function DoStuff(SourceStream: TMyCustomStream);
begin
data := SourceStream.ReadDWord;
otherData := SourceStream.Read(Buffer, 20);
end;
Run Code Online (Sandbox Code Playgroud)
首先:Delphi中不可能实现多重继承.
您说自定义流类的方法对它们都实现相同吗?您可以以流阅读器类的形式使用装饰器模式.
另一方面,您可以TStream通过为其编写类助手来扩展:
TCustomStreamHelper = class helper for TStream
function ReadByte: byte;
function ReadWord: word;
function ReadWordBE: word;
function ReadDWord: longword;
function ReadDWordBE: longword;
function ReadString(Length: integer): string;
function ReadBlockName: string;
// etc.
end;
Run Code Online (Sandbox Code Playgroud)
因此,在TCustomStreamHelper编译器已知的每个单元中(因为您将其单元添加到uses子句中),您可以TStream像使用其他方法一样使用几个世纪.
要回答实际问题标题中的问题: 你不能.:)
但是,如果我们退一步看看你试图解决的问题:
我有一个继承自TFileStream的类和一个继承自TMemoryStream的类.两者都实现与读取数据完全相同的功能
我认为你错误地陈述了你的问题并正确地重新说明了你需要的答案.:)
I have some structured data that I need to read from different sources (different stream classes).
Run Code Online (Sandbox Code Playgroud)
流只是一堆字节.在这些字节的任何结构由以下因素决定如何你读/写流.即在这种情况下,"如何"体现在你的功能中.涉及的具体流类是TFileStream和TMemoryStream这一事实并不是问题的根本部分.解决TStream的问题,然后为所有TStream派生类解决它,包括你现在正在处理的那些.
流类应根据它们如何在特定位置(内存,文件,字符串等)中读取/写入字节而不是那些字节中的任何特定结构来进行专门化.
您不需要创建必须复制结构知识的专用流类,而是真正需要的是一个类,它封装了所涉及数据结构的知识,并能够将其应用于任何流.
一种方法(最好的?)是实现一个封装所需行为的类.例如,在"读者"类中.
TStuffReader = class
private
fStream: TStream;
public
constructor Create(aStream: TStream);
function ReadByte: byte;
function ReadWord: word;
function ReadWordBE: word;
function ReadDWord: longword;
function ReadDWordBE: longword;
function ReadString(Length: integer): string;
function ReadBlockName: string;
end;
Run Code Online (Sandbox Code Playgroud)
这个类也可以编写提供的功能,以流以及(在这种情况下,你可以称之为TStuffFiler,例如,因为它不只是一个阅读器),或者你可能有写作称为一个单独的类 TStuffWriter(用于例).
无论您选择实现它,此读者类都能够从/向任何 TStream派生类读取(和/或写入)结构化数据.对于这些函数而言,涉及哪些特定类的流并不重要.
如果您的问题包括需要将对流的引用传递给各种函数等,那么您将传递对reader类的引用.读者必须带有对所涉及的流的引用,但是之前您认为需要在专用流类上调用函数的代码只是使用读取器函数.如果该代码还需要访问流本身,则读者可以在必要时公开它.
然后在将来,如果您发现自己需要从其他流类中读取此类数据(例如TBLOBStream,如果您发现自己从数据库中检索数据),您的TStuffReader(或您选择调用它的任何内容)可以直接进入并执行你的工作没有任何进一步的工作.
类助手似乎提供了一种近似"多重继承"的机制,但应该避免使用.它们从未打算用于应用程序代码.
VCL中类助手的存在正如您所期望的那样,因为它们旨在用于框架和库,而VCL是一个框架库,因此它的使用完全符合该用法.
但这并不表示它们适合在应用程序代码中使用,文档继续强制执行这一点.
类和记录助手提供了一种扩展类型的方法,但它们不应被视为在开发新代码时使用的设计工具.对于新代码,您应该始终依赖于普通的类继承和接口实现.
文件也很清楚适用于课堂助手的限制,但没有明确解释为什么这些可能导致问题,这也许是为什么有些人仍然坚持认为它们适合使用.
我在介绍后不久就在博客文章中介绍了这些问题(今天仍然存在同样的问题).事实上,这是一个问题,我写了一些关于这个主题的帖子.
似乎不愿意放弃这样一种观念,即只要你小心你的帮助者那么你就不会遇到问题,这就是忽略了这样一个事实:无论你多么小心,你使用助手都可以如果你最终与他们分享代码,那么别人小心使用会打破他们.
并且Delphi中没有比VCL本身更多的共享代码.
在VCL中使用(附加)助手会使您更有可能与自己的助手发生问题,而不是更少.即使您的代码在一个版本的VCL中与您自己的帮助程序完美配合,下一个版本也可能会破坏.
它们不仅不是建议更多使用助手,而是在VCL中的扩散只是你应该避免它们的一个很好的理由.
| 归档时间: |
|
| 查看次数: |
388 次 |
| 最近记录: |