如何判断一个实例是否属于某个类(不包括其派生类)(50分)

  • 主题发起人 陈冲伟
  • 开始时间

陈冲伟

Unregistered / Unconfirmed
GUEST, unregistred user!
A.T.T. 用is会把派生类的实例也算进去。
 
C

creation-zy

Unregistered / Unconfirmed
GUEST, unregistred user!
ClassName is OK!

procedure TForm1.Button1Click(Sender: TObject);
var
mstr:String;
begin
mstr:=Sender.ClassName
//or Button1.ClassName、Form1.ClassName ...
Caption:=mstr;
if mstr=TObject.ClassName then
ShowMessage('OK!');
end;
 
P

plaw

Unregistered / Unconfirmed
GUEST, unregistred user!
TObject.ClassName is a virtual function
 
C

creation-zy

Unregistered / Unconfirmed
GUEST, unregistred user!
非也,证据如下:

System.pas

TObject = class
...
class function ClassName: ShortString
//类方法
...
destructor Destroy
virtual
//这才是虚方法
end;

不信的话看一看这一句的执行结果吧:

procedure TForm1.Button1Click(Sender: TObject);
begin
Caption:=TObject.ClassName
//the result is 'TObject'
end;
 
P

plaw

Unregistered / Unconfirmed
GUEST, unregistred user!
我所谓的virtual并不是声明的时候的virtual。
请看ClassName的实现。
class function TObject.ClassName: ShortString;
asm
{ -> EAX VMT }
{ EDX Pointer to result string }
PUSH ESI
PUSH EDI
MOV EDI,EDX
MOV ESI,[EAX].vmtClassName //注意这里
XOR ECX,ECX
MOV CL,[ESI]
INC ECX
REP MOVSB
POP EDI
POP ESI
end;
另外,你的例子中的写法不妥。
如果这么些,你看看结果。
Caption := Button1.ClassName;
 
P

plaw

Unregistered / Unconfirmed
GUEST, unregistred user!
补充一句,这应该叫做多态
 
C

ColorOfWind

Unregistered / Unconfirmed
GUEST, unregistred user!
同意PLAW的说话,CLASSNAME是一个类方法,也是一个虚方法,正是因为它是虚方法,
才可以被子类用如下的方式引用:
procedure TForm1.Button1Click(Sender: TObject);
begin
Caption:=Sender.ClassName

end;
结果为TButton。
这种引用方式实际上就是多态性。
另外说明一下,CLASSNAME是获得运行期类型信息(RTTI)的方法,相关的函数还有
CLASSTYPE、CLASSPARENT、CLASSINFO等等,它们使程序可以在运行期获取一个对象的类型
信息。
应该清楚了吧
 

温柔一刀

Unregistered / Unconfirmed
GUEST, unregistred user!
呵呵,对于陈冲伟的原问题,ClassName恰好是解决方法

其它问题嘛,各位说的也都对。。。。 :)

 
C

creation-zy

Unregistered / Unconfirmed
GUEST, unregistred user!
plaw:
不好意思,我把您的意思理解错了——我以为您说的是纯虚方法。
不过,我在前面可是举过 mstr:=Sender.ClassName
的例子哟。 :)

另外,我认为ClassName方法不能说成是虚方法——因为所有的派生类的ClassName方法
的入口都是这个函数,而不是其它的函数。它之所以能过达到类似于“多态性”的效果,
仅仅是因为在函数的内部使用了VMT表中的信息,发生变化的是VMT中的信息,而函数本身
对任何类来说都是一样的。如果一定要说“多态性”的话,我只能说ClassName方法具有
调用虚方法vmtClassName的能力,而ClassName方法本身并不是虚方法。
以上观点有何错误之处,还请大家指正。
 
C

ColorOfWind

Unregistered / Unconfirmed
GUEST, unregistred user!
P

plaw

Unregistered / Unconfirmed
GUEST, unregistred user!
同意creation-zy
 
F

fbyang

Unregistered / Unconfirmed
GUEST, unregistred user!
IF 控件1.inheritedfrom(类1) then
showmessage('控件1是从类1继承下来的!') ;
如果是判断控件1的类是类1,可以这样:
if 控件1.classname = '类1的名字' then
showmessage('pk!')
 

陈冲伟

Unregistered / Unconfirmed
GUEST, unregistred user!
多谢各位
 

陈冲伟

Unregistered / Unconfirmed
GUEST, unregistred user!
多人接受答案了。
 
M

majorsoft

Unregistered / Unconfirmed
GUEST, unregistred user!
虚拟的类方法实现了类一级的多态性。
这可以说是Delphi所特有的特性
 
A

aimingoo

Unregistered / Unconfirmed
GUEST, unregistred user!
OH~今天才发现creation-zy的这个贴子,不过很遗憾地说:creation-zy建议用ClassName的方法是不正确的。

ClassName看起来很明显地表示了父类的名称。但是,显然我们可以定义两个相同名称的类。也就是说,在这种情况下,ClassName是歧义的。

正确的方法应当是这样:
-----------
1. 识别两个对象是否是同一个类的实例:
if (Obj_A.ClassType = Obj_B.ClassType) then ...

2. 识别一个对象是否是一个类的实例:
if (Obj.ClassParent = aClassRef) then ...

下面给出两个函数:
-----------
function ObjectSame(Obj1, Obj2 : TObject) : Boolean;
begin
Result := Obj1.ClassType = Obj2.ClassType;
end;

function ClassIs(Obj: TObject
ClassRef: TClass) : Boolean;
begin
Result := Obj.ClassParent = ClassRef;
end;
 

Similar threads

S
回复
0
查看
947
SUNSTONE的Delphi笔记
S
S
回复
0
查看
768
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
顶部