Delphi的OOP概念方面的问题。不是小气。只有300分。(300分)

  • 主题发起人 主题发起人 zw960122
  • 开始时间 开始时间
Z

zw960122

Unregistered / Unconfirmed
GUEST, unregistred user!
Virtual方法及Dynamic方法大家一定了解吧。我就由这里开始我的问题。是一系列的呀。(1)我们把问题实例化一点。在Class.pas 中有一个对象TCollection对象中有一个方法constructor Create(Collection: TCollection); virtual;
它的父类的父类TObject也有一个方法Create.
问题出现了。子类中使用方法名称与父类〔再父类〕的方法名相同而参数不同时,后缀应该是什么呢?
换个说法。
type
  TMyClass = class
   procedure One;virtual;
  end;
  
  type
  TNewClass = class(TMyClass)
   procedure One;virtual;
  end;
这段代码也对了?不是吧。
  

(2)我看到一个abstract后缀。帮助中有一段话。不知怎么翻译。
You can call an abstract method only in a class or instance of a class in which the method has been overridden.
我译的结果是:你只能在一个类中或一个派生类的实例中调用abstract方法。不明白是什么意思。
以TStrings为例。insert 方法如下声明:
procedure Insert(Index: Integer; const S: string); virtual; abstract;
有一个派生类TStringList
使系统有了多态性的特点。但abstract的作用是什么呢。是使TStrings不能建立自己的实例吗。那就是说abstract不是必须的了。应该不是这样吧。谁能告诉我abstract后缀的必要性是什么呢?不用行不行?

 
看过Delphi的Thread例子吗?
看一看或许会明白写!!!
如果不清楚,最好是搞一本C++的书看一看!!!
 

!#—#¥……—·
 
使用abstract是告诉你,这个方法在子类中必须被覆盖,否则就会出错或不能
实现预定功能。
另一个有趣的例子:
---------------------------------------------------------------------------
procedure One;virtual;
implementation
procedure One;
begin
end;
----------------------------------------------------------------------------
这和
procedure One;virtual;abstract;在实现上简直没什么区别。但不加abstract是告诉
你这个方法在子类中不一定要被覆盖。

 
(1)不太明白你的意思
(2)以TStrings为例,你不能Aobj:=TStrings.Create,因为TStrings中有abstract的Insert,
你只能创建它的实现类,如:Aobj:=TStringList.Create
abstract的意思是在类中申明了方法但没有实现它
(3)建议你多看delphi的源程序
 
1、如果你的继承类中也是virtual,就没必要声明该方法
2、应该如下翻译:
你只能在一个overridden基类方法的类中或派生类的实例中调用该方法。
abstract是先申明一个以后用的着的方法,比方基类中一般只有行为
 
You can call an abstract method only in a class or instance of a class in
which the method has been overridden.
翻译的结果应该是:
只有当一个类override了(父辈的class)抽象方法后,你才可以呼叫这个方法。

abstract的作用是体现OOP的多态,
这是因为TStrings这个类比较抽象,就象是“车”,很抽象,它知道有门这属性,
但却不可以实作出门这东西,只有到了具体的车类后后才实现“门”,比如轿车的门,
解放汽车的门,这两种车具体做出了门是什么样子的,它们的门都不是一样的,颜色啊,形状啊等等;
TStrings也是这样,它有Insert这个方法,但却不可以做出Insert到底怎么做,
因为它的子类各有各的Insert方式,所以它在这里先定义这么一个框架,让子类知道,
他们这个物种有这种方法,又比如灵长类动物,都有嘴巴,所以只有有嘴巴的灵长动物,
没有不长嘴巴的灵长动物,在解释灵长动物时,必须把嘴巴也说上去一样,TStrings也一样,
它只有有了Insert方法后,才表现出它是一个TString(这又回到对Tstrings类这个东西的理解了,
有人说,我的Tstrings有InsertTwoRecord才是Tstrings的,而且必须是没有Insert,
有Insert就不是我说的TStrings,那么你说呢)
但你能说灵长类动物的嘴巴都象人这样吗?不能,人的嘴巴和猴的嘴巴是有不同的,。
再回到TStrings,我们可以这么使用它:
begin dosomething;
var a: TStrings;
begin
a:=TStringList.Create;//
a.Insert();//
end;
回到那句英语句子。a是TStrings,它没有实作出Insert,它只能调用实例化类中的方法,
也就是它调用了TStringList.Insert方法。

如果想彻底搞懂virtual有一本解释得非常详细,就是钱达智的《Delphi学习笔记 for win32》
除了virtual还有dynamic。
我认为这些东西是Delphi中OOP的精华。
 
楼上的兄弟真是谢谢了。打字很辛苦。不妄我300分。谢了。不过有没有再好的。
请看http://download.pchome.net/user/delphi/deeperindelphi1.htm。
有没有能解决我的问题的。
问题〔1〕为什么不用overload.
问题〔2〕为什么一定要用abstract。不用不行吗。
 
关注这方面。。。。。
 
type
  TMyClass = class
   procedure One;virtual;
  end;
  
  type
  TNewClass = class(TMyClass)
   procedure One;virtual;
  end;
你的代码有问题,TnewClass是从TmyClass继承来的,
TmyClass中的one方法,是抽象的方法,你并没有实现它,
而你在TnewClass中又把它定义为一个虚拟方法,编译时
是不能通过的,你在TmyClass中定义的方法在TnewClass
重载来实现,这也就是我们说的多态
TNewClass = class(TMyClass)
   procedure One;override;
  end;
implementation
TnewClass.one;
bging
end;
 
to zw960122:
我不知你有没有看我上面的回答,你的问题〔2〕已经解决。我再说一遍,如果
父类的虚函数子类不一定要继承就不必加abstract,反之则加。
另:问题〔1〕的overload不知你用在何处。
 
http://download.pchome.net/user/delphi/deeperindelphi1.htm
已经讲得很明白了。如果我知道的话也会把那些再贴上来而已。
 
overload的使用情况,如果要声明的方法含有它祖先类不同的参数信号,
它将overload掉继承的方法,而不是将父类的方法隐含掉。
呼叫子类的方法,将用匹配于呼叫参数的那个方法!去实现。
type

T1 = class(TObject)
procedure Test(I: Integer); overload; virtual;
end;
T2 = class(T1)
procedure Test(S: string); reintroduce; overload;
end;
...
SomeObject := T2.Create;
SomeObject.Test('Hello!'); // calls T2.Test
SomeObject.Test(7); // calls T1.Test
由此可以了解override和overload的不同。
 
在一个类内,你不能用同样的名字去发表多个overload方法,
运行时类型信息的维护需要每一个发表了的成员都拥有唯一的名字。
type
TSomeClass = class
published
function Func(P: Integer): Integer;
function Func(P: Boolean): Integer // error
 
要使一个方法虚拟或动态,在声明的时候要包含virtual或dynamic指示。
虚拟方法和动态方法不象静态方法,能够被后代类override掉。
当一个override了的方法被呼叫的时候,被使用的实际(运行时)类或对象的方
法被调用--而不是声明变量时的那个类--决定于哪种类的实现被激活。

要override一个方法,在重新声明的方法包含overridde指示。一个override
声明中变量顺序和类型及结果类型必须和祖先类的声明相匹配
在正面的例子中,声明在TFigure中的方法被两个子类分别override掉。
type

TFigure = class
procedure Draw; virtual;
end;
TRectangle = class(TFigure)
procedure Draw; override;
end;
TEllipse = class(TFigure)
procedure Draw; override;
end;

做了这些声明后,下面代码举例说明,呼叫变量虚拟方法的效果,这变量的实际类型在运行时是不同的
var

Figure: TFigure;
begin
Figure := TRectangle.Create;
Figure.Draw; // calls TRectangle.Draw
Figure.Destroy;
Figure := TEllipse.Create;
Figure.Draw; // calls TEllipse.Draw
Figure.Destroy;
end;
只有virtual和dynamic方法能够被override掉,尽管如此,其它方法,可以使用overload
 
overload->重载; 是一个类中的多个同名方法,带不同参数表;
override->覆盖; 是一个父类的多个子类的同名方法,参数应该相同;

都是多态的表现。
 
关于abstract:
Delphi控件的有些方法声明(declared)成abstract(抽象)。
在VCL和CLX,抽象方法通常发生在一些名字由由"custom"的类中,
比如TCustomGrid。这些类本身就是抽象的,在理解上它们是只有意做为一些子孙类的起源。
虽然你可以建立包含一个抽象部份的对象或类,但并不推荐这么做。
呼叫抽象部份的时候会导致EAbstractError异常。
abstract指示用于指出类的一些部份只是表面的东西,且在子孙类中定义;
它强迫控件开发者在实际类的实例能被建立前要重新声明子孙类的抽象部分。
 
我将我的理解整理了一下,放在我的网站上。
http://www.isunsoft.com/技术论坛中的Delphi专栏

http://www.isunsoft.net/forum/link.asp?TOPIC_ID=204
 
感谢各位的支持。在这里有我见过的Delphi最贵的书--钱哥的
《Delphi学习笔记 for win32》〔580大洋〕。
有几位同仁的精彩论坛:
http://download.pchome.net/user/delphi/deeperindelphi1.htm
http://www.isunsoft.net/forum/link.asp?TOPIC_ID=204
http://www.csdn.net/expert/topic/477/477402.shtm
感谢大家的支持。我已经没分了。但还有一个问题。正是在这个问题的基础上提出来的。
这里不懂下面的问题更不好办。CSDN上有分,可以给很多。
论坛地址:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=858750
 
这本书我看过,对提高Delphi OOP方面的知识《Delphi学习笔记 for win32》这本书确实有很大的帮助
值得大力推荐。
 
后退
顶部