类的继承---跨过中间类,继承祖先类的方法(80分)

  • 主题发起人 主题发起人 xbl
  • 开始时间 开始时间
X

xbl

Unregistered / Unconfirmed
GUEST, unregistred user!
有3个类 A,B,C,继承关系 A-->B-->C,
A中有一个虚拟对象方法 Fun、B、C分别重载这个方法,
现在C要继承 A.Fun 而不是 B.Fun.
如何才能做到?

type
A = class
public
procedure Fun
virtual;
end;

B = class(A)
public
procedure Fun
override;
end;

C = class(B)
public
procedure Fun
override;
end;

implementation

procedure A.Fun;
begin
ShowMessage('A');
end;

procedure B.Fun;
begin
ShowMessage('B');
end;

procedure C.Fun;
begin
//在这里调用A中的Fun,怎么可以做到???
//这样试过:
//1 (Self as A).Fun 可以编译通过,但结果不对。
//2 A(Self).Fun
可以编译通过,但结果不对。
end;
 
这位兄台,好像不能实现吧! 我当初也有过你这样的需求,
TMyGrid -> TCustomDBGrid -> TCustomGrid ,我当初也是想直接过载一个已经被
TCustomDBGrid 过载了的TCustomGrid的方法,但是好像行不通的。
 
宁柯:
谢谢您的关注!

我在这里等了很久了,唉,我想了几个小时,没有丝毫头绪!
我记得在 C++里面可以实现,都是类,为什么用 Object Pascal 就不能实现呢?
如果真的不能实现,看来我只能从 A 继承了,但这样得自己作很多的事情啊,因为
在B里面实现了很多方法,从A继承就得自己实现B中得方法了!
 
看看
procedure C.Fun;
begin
INHERITED;//看看有什么反映!再说1
//在这里调用A中的Fun,怎么可以做到???
//这样试过:
//1 (Self as A).Fun 可以编译通过,但结果不对。
//2 A(Self).Fun
可以编译通过,但结果不对。
end;
 
//这样可以
procedure C.Fun;
Var aa:a;
begin
aa:=a.Create();
aa.Fun ;
aa.Free;
end;
如果这个是你的类实际的设计话
我劝你重新考虑你的继承关系 c直接从a继承下来
我觉得不太符合使用面向对象的初衷
不知道你对象都代表什么 为什么这么设计
如果可以 把你的ABC类都代表什么贴出来 大家讨论一些
 
卡色:
procedure C.Fun;
begin
inherited;
end;

这样显示的结果自然是 B.

测试:
procedure TForm1.Button1Click(Sender: TObject);
var
X: C;
begin
X := C.Create;
X.Fun;
X.Free;
end;

 
例:
C++中:
class A

Class B : public A

Class C : public B

在 C的此虚函数中
C::Fun
{
A::Fun;
}
就行了
 
To:卡色
您加上 INHERITED 这一句,等于告诉C.Fun 首先执行B的Fun,然后进行下面的处理,
我估计可能还是不行吧。
当然没有实践就没有发言权,如果我真的错了,不要笑话我哦! :)
 
北冥有鱼:
谢谢您的关注!
我也是这么想,我也正是改变了继承关系来解决问题的,
我把 C = class(B) 改成了 C = class(A) 。
因为是这样的:A,B,是已经设计好的类,不是我设计的,我觉得直接从 B 继承可以
省好多事,于是就打算从B继承了A,但是就遇到了上面的问题,现在我就很想知道,
为什么C中可以跨过父类而去继承祖先类,为什么 Object Pascal 就不可以呢?
真的没有办法可以做到吗?
 
北冥有鱼:
我的调用A.Fun的目的是: 通过在 C.Fun 中调用A.Fun来改变C中一个私有变量的值。
只有一个对象,不能再创建A对象啊。
我现在在网吧上网,记不清A,B,C 具体是什么了,反正比较冗长。
我要实现的目的是:A,B与C不在一个单元,因此C不能访问从 A 继承下来的私有变量,
现在我需要对私有变量操作,而这个操作呢,A.Fun就做到了,因此我就想调用A.Fun。
接着再做其他的事情,Crane说得不错,在C中是很容易实现的,我试过了!
都是类,为何用 Object Pascal 就不可以呢?

宁柯:
您说得不错,在 C.Fun中加上 inherited,其实就是调用 B.Fun.我试过啦。

大家再帮我想想吧!

 
这样呢?
procedure C.Fun;
begin
(Self.ClassParent.ClassParent as A).Fun ;
end;
 
在A中添加一个虚方法(比如FunForC,功能与A.Fun一样),在B中不要覆盖它,在C中调用即可。
 
如果有源代码, 即使不在同一单元内也能修改任意级父类中的私有变量的。
另外, 也有办法调用跨级父类中的被覆盖的方法, 就是通过父类实例的VMT(Virtual Method Table)找到该方法的入口地址然后直接调用。
不过很麻烦。 不如直接修改私有变量简单。
 
谢谢大家的关注!

Crane:
这样编译不通过!

Tangle:
A 类已经设计好了,我不希望再去修改它,我只是想知道如何跨过父类而去访问祖先类!

Another_eYes:
下面是我的测试代码:

//类申明单元:
unit uClass;

interface
uses Dialogs;

type
TA = class
private
FNote: string;
public
procedure Fun(S: string)
virtual;
end;

TB = class(TA)
public
procedure Fun(S: string)
override;
end;

implementation

{ A }

procedure TA.Fun(S: string);
begin
FNote := 'A' + S;
ShowMessage(FNote);
end;

{ B }

procedure TB.Fun(S: string);
begin
FNote := 'B' + S;
ShowMessage(FNote);
end;

end.

//子类单元
type
TC = class(TB)
public
procedure Fun(S: string)
override;
end;

implementation

{ C }

procedure TC.Fun(S: string);
begin
//这里,我希望给私有变量赋值 FNote := 'A';
//如果直接继承 inherited
那么继承的是B的: FNote := 'B' + S;
end;

说明:
1 加入Dialogs 的目的只是为了测试是用,调用 ShowMessage过程。
2 我的目的只是想知道如何跨过父类去访问祖先类,
若只是为了实现,我是可以直接从祖先类继承的!
3 如果这个过程 Fun 没有参数的话,我可以这样实现,而且已经通过了!
procedure TC.Fun;
begin
asm
TA.Fun;
end;
end;
一旦加了参数就报错了!
但我是希望能够传入参数的 !




 
在C类中你完全可以不覆盖A类的方法,这样就就可以了吗
 
测试:
procedure TForm1.Button1Click(Sender: TObject);
var
X: TC;
begin
X := TC.Create;
X.Fun('X');
X.Free;
end;

我希望弹出的信息是: ‘AX’,而不是‘BX’

 
这个问题可以这样解决,在重载虚函数的时候,不用默认的Inherited,而写为
Inherited ClassParent.ClassParent.函数名即可。
 
to Another_eYes,
>>即使不在同一单元内也能修改任意级父类中的私有变量的。
好像只能修改protected的数据吧,私有变量也能修改吗?!!!如何做???
哦,我明白了你说的是aimingoo的《如何跨单元、跨类地访问Delphi类的私有域》
(参见http://aiming.ynxx.com/).

>>通过父类实例的VMT(Virtual Method Table)找到该方法的入口地址然后直接调用。
这个如何做到呢?

to xbl,
procedure C.Fun;
begin
//在这里调用A中的Fun,怎么可以做到???

//在这里直接拷贝A.Fun的代码吧,当然如果要访问到A的私有变量/方法/过程的话那就
//比较麻烦了!
end;
 
xasgl:
这样好像不可以,我刚刚试了。
Inherited ClassParent.ClassParent.函数名
这样不会出那个函数名啊,我把它转换了一下
Inherited (ClassParent.ClassParent as TA).函数名 也不行!

唉,我想了好久了,没有丝毫头绪!
 
关注册资金!!!


 
后退
顶部