求助yysun兄,flier兄,dream_soft兄。。。。。。(200分)

  • 主题发起人 主题发起人 6559026
  • 开始时间 开始时间
6

6559026

Unregistered / Unconfirmed
GUEST, unregistred user!
yysun兄的观点:
我的观点很简单:要把 GP 应用到 Delphi:
1、固定到类里去的做法已经有了如 TList,
2、用 ADT 基本上是模仿 C++ 的纯虚拟类,应该考虑为什么 C++ 没有这么做?
RTTI 只是个补丁而已。
3、因为没有 C++ 的 template ,唯一可行的只能参照 Java,用 interface了。

对于以上的实现方法,我只有八分的理解和设计思路,兄台有否新观点、新资料?
能否寄给小弟一份?左兄的实现方法有一个本质问题是:object pascal中对象的
拷贝是应用,这给赋值语句带来极大的不便,怎么解决?

flier兄,dream_soft兄;如果有时间的话同样请帮忙,小弟急,目前我要做的工作
就是实现一个object pascal的GP实例?。。。?!!!

即要实现类型参数化和子程序参数化,类型参数化还算有一点眉目,子程序参数
化还在考虑中。请高手give me a hand
 
email :brandnewday@263.net
 
sorry, 最近很少到这里来,刚刚才看到你的问题 :)
>1、固定到类里去的做法已经有了如 TList,
>2、用 ADT 基本上是模仿 C++ 的纯虚拟类,应该考虑为什么 C++ 没有这么做?
> RTTI 只是个补丁而已。
这里不存在谁模仿谁的问题,因为C++和Delphi在设计思路上很多地方都不一样,
如果硬要互相模仿,只会适得其反,必须遵照语言本身的设计思路,发挥自己的长处才行
至于RTTI,对C++来说是个补丁,但对Delphi/Java/C#这样的语言来说,是基础 :)

>3、因为没有 C++ 的 template ,唯一可行的只能参照 Java,用 interface了。
照我的观点,GP和template并非密不可分,不过考虑到yysun兄的观点,就不多说了,呵呵
前段时间看到borland上面有篇文章谈到在Delphi里面模拟template的方法,
虽然缺点不少,但还是一个很好的思路,你可以看看
http://community.borland.com/article/0,1410,27603,00.html

>对于以上的实现方法,我只有八分的理解和设计思路,兄台有否新观点、新资料?
>能否寄给小弟一份?左兄的实现方法有一个本质问题是:object pascal中对象的
>拷贝是应用,这给赋值语句带来极大的不便,怎么解决?
可以用AObj.Assign(OtherObj)了。运算符重载是C++的一个功能,但并非OO或者GP的必须,
只要能达到Assignable的Concept,用什么方法都不是问题。

> 即要实现类型参数化和子程序参数化,类型参数化还算有一点眉目,子程序参数
>化还在考虑中。请高手give me a hand
实际上凡是关于静态的东东,在Delphi里面都是令人非常头痛的,呵呵
Delphi/Java这种语言在设计上就合C++有很大分别,因为C++中为了编译时处理
达到效率最优化等多方面原因,而Delphi/Java则更看着运行时的灵活性,
加上Delphi里面又缺少inner class, namespace等等概念,比java更让人头痛
目前我所能想到的最好的在类里面使用静态数据来表现类的Traits等思想的办法,
就是通过类方法,也就是class procedure等等,我的那个GP实现的试验中很大程度
上就依赖这个东东,更妙的是类方法和普通方法一样,还可以有多态行为,呵呵
 
呃,又来了?蹲一边看着先……
 
听!
虽然对算法以外的东西不大感兴趣!
http://delphi.about.com/library/weekly/aa010201a.htm
 
>我的那个GP实现的试验中很大程度
>上就依赖这个东东,更妙的是类方法和普通方法一样,还可以有多态行为,呵呵

to flier:
能否发来共享?
brandnewday@263.net
 
to 6559026:
GP思想很好,实现起来的确让人头痛,特别是在看惯了C++的Template思路后,
如何从中跳出来以Delphi的思路来实现,是个大问题。因为C++和Delphi的语言在设计
上走的两条不同的道路,前者注重效率,偏向于编译期处理,因此大量使用静态帮定
编译期类型检查;后者注重灵活性,偏向于运行期处理,因此强调RTTL,单根类树
这就注定在Delphi中模仿C++的Template风格是无法或不容易实现的。

因此,在Delphi里面实现GP,我以为只能以牺牲一定的效率为代价,在运行期做
一些看似应该由编译器在编译期做的事情,比如在你所说的Assignable concept中
我们必须代替编译器检查赋值类型是否与自己相同,方法是通过单根类树判定两者间关系
如可以用TObject.ClassType判定两者是否相同,也可以用TObject.InheritsFrom
判定两者见的继承关系等等,然后通过一定的规则来决定是否允许进行Assignable操作
如不允许可以动态抛出异常,允许则通过向两者之一取得IAssignable接口进行赋值操作
此接口可以很简单,IAssignable.Assign(...)一个方法即可。这样看似繁琐,但是
有其特有的灵活性,可动态进行处理,不受编译期的限定。
下面举一个简单的例子说明我的观点:

IAssignable 接口表示 Assignable Concept,TAssignableObject和
TChildObject是两个简单的类,实现IAssignable接口,在Assign方法中,
判断参数是否为自己的子类,因为只能将子类赋值给父类(但数据被截断),反之不行
如否则抛出异常,如是则取得本类树层次的数据,使用起来很简单,也可以用 a = b = 0
类似的形式,如Obj1.Assign(Obj2.Assign(Obj3))


和C++的实现相比,此实现效率较低,但灵活性大大增加,不必象C++那样在编译时
就必须知道所有的细节,可以灵活地在运行时通过配置修改软件的behaviour,
而效率方面的损失,在硬件飞速升级的今天,实在没有太多值得担心的,毕竟一个界面
在100ms和200ms内响应对用户没有太大区别(何况不至于有这么大区别:)

type
IAssignable = interface
['{65035B8F-968F-4ED8-B57E-1CC75EC7AE52}']
function Assign(Obj: TObject): TObject;
end;

TAssignableObject = class(TInterfacedObject, IAssignable)
private
FValue: Integer;
protected
{ IAssignable }
function Assign(Obj: TObject): TObject
virtual;
public
constructor Create(AValue: Integer);
property Value: Integer read FValue;
end;

TChildObject = class(TAssignableObject)
private
FText: string;
protected
{ IAssignable }
function Assign(Obj: TObject): TObject
override;
public
constructor Create(const AText: string
AValue: Integer);
property Text: string read FText;
end;

EAssignable = class(Exception);

{ TAssignableObject }

constructor TAssignableObject.Create(AValue: Integer);
begin
inherited Create;

FValue := AValue;
end;

function TAssignableObject.Assign(Obj: TObject): TObject;
begin
if not Obj.InheritsFrom(Self.ClassType) then
raise EAssignable.CreateFmt('赋值操作必须在两个同类型对象间进行![%s <> %s]',
[Self.ClassName, Obj.ClassName]);

FValue := (Obj as TAssignableObject).FValue;

Result := Self;
end;

procedure TfrmMain.btnAssignClick(Sender: TObject);
var
Obj1, Obj2, Obj3: TAssignableObject;
begin
Obj1 := TAssignableObject.Create(1);
Obj2 := TChildObject.Create('Hello', 2);
Obj3 := TChildObject.Create('World', 3);

Obj1.Assign(Obj2.Assign(Obj3));
ShowMessage(Format('Obj1 = [%d], Obj2 = [%s, %d]',
[Obj1.Value, TChildObject(Obj2).Text, TChildObject(Obj2).Value]));

Obj2.Assign(Obj1);
end;

{ TChildObject }

function TChildObject.Assign(Obj: TObject): TObject;
begin
Result := inherited Assign(Obj);

FText := (Obj as TChildObject).FText;
end;

constructor TChildObject.Create(const AText: string
AValue: Integer);
begin
inherited Create(AValue);

FText := AText;
end;


 
to all
到底什么是GP?
依愚之见就是做到类型参数化和子程序参数化,这样看来,c++如果不能做到子程
序参数化的话,用它来实现GP也不是很方便。
 
接受答案了.
 
后退
顶部