特别是,我觉得有必要在TCharacter.IsLatin1
这private
。
type
TCharacterHelper = class helper for TCharacter
public
class function IsLatin1(C: Char): Boolean; static; inline;
end;
class function TCharacterHelper.IsLatin1(C: Char): Boolean;
begin
Result := Ord(C) <= $FF;
end;
这种单线方法几乎可以立即重新实现,但是我最好还是让供应商自行决定确切的实现细节。
有什么办法可以“重新引入”这种方法来public
提高知名度?
请参阅下面的更新
众所周知,助手确实会破坏个人的知名度。因此,可以从班级助手中看到私人成员。但是,此行为不会扩展到静态成员,因此TCharacter.IsLatin1
在声明它的单元之外无法访问(通过公平的方式)。
那不公平的手段呢?好吧,有一些公开的TCharacter
do方法IsLatin1
。即使IsLatin1
声明inline
了这些方法,也似乎这些方法是使用call语句而不是内联的代码编译的。可能是因为它们的调用发生在相同的单元或相同的类型中,并且内联引擎无法内联。
无论如何,我要这样做的地方是,您可以在运行时分解其中一个调用。为了争辩,让我们考虑IsControl
:
class function TCharacter.IsControl(C: Char): Boolean;
begin
if IsLatin1(C) then
Result := InternalGetLatin1Category(C) = TUnicodeCategory.ucControl
else
Result := InternalGetUnicodeCategory(UCS4Char(C)) = TUnicodeCategory.ucControl;
end;
它的第一个动作是调用IsLatin1
。编译后的代码如下所示:
System.Character.pas.517: 00411135 C3退出 00411136 8BC0 mov eax,eax TCharacter.IsControl: 00411138 53 push ebx 00411139 8BD8 mov ebx,eax System.Character.pas.533: 0041113B 8BC3 mov eax,ebx 0041113D E852FFFFFF呼叫TCharacter.IsLatin1 00411142 84C0测试al,al 00411144 740F jz $ 00411155
因此,您可以执行以下操作:
TCharacter.IsControl
。call
条指令。call
指令进行解码以找到目标地址,IsLatin1
即可在此处找到目标地址。我并不是很赞成这个IsLatin1
。这是一个简单的函数,并且不受更改,因此重新实现它肯定更好。但是对于更复杂的情况,可以使用此方法。
而且我也没有要求独创性。我从madExcept源代码中学到了这项技术。
好的,@ LU RD足智多谋地找到了一种证明我错误的方法。对此表示祝贺。我所说的static
方法是准确的,但是@LU RD使用了非常熟练的技巧来引入非静态类方法,从而破解了私有成员。
我想进一步说明他的答案,方法是显示如何使用两个助手使用原始名称公开该功能:
unit CharacterCracker;
interface
uses
System.Character;
type
TCharacterHelper = class helper for TCharacter
public
class function IsLatin1(C: Char): Boolean; static; inline;
end;
implementation
type
TCharacterCracker = class helper for TCharacter
public
class function IsLatin1Cracker(C: Char): Boolean; inline;
end;
class function TCharacterCracker.IsLatin1Cracker(C: Char): Boolean;
begin
Result := TCharacter.IsLatin1(C); // resolves to the original method
end;
class function TCharacterHelper.IsLatin1(C: Char): Boolean;
begin
Result := TCharacter.IsLatin1Cracker(C);
end;
end.
您可以使用此单元,并且在该单元之外活动的唯一帮助程序是在接口部分中声明的帮助程序。这意味着您可以编写如下代码:
{$APPTYPE CONSOLE}
uses
System.Character,
CharacterCracker in 'CharacterCracker.pas';
var
c: Char;
begin
c := #42;
Writeln(TCharacter.IsLatin1(c));
c := #666;
Writeln(TCharacter.IsLatin1(c));
Readln;
end.
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句