type TProduct = class private FName :String; FPrice :Float; // protected // public // published // end;type TStore = class private FProduct :TProduct; //这里就是仓库拥有商品 // protected // public // published // end;
对qybao(阿宝)作答之拾遗: 首先,qybao(阿宝)的作答很基础,其指出了解决该问题的本质方法。其实,在OO中,表示两种类(两个对象)之间的这种关系的概念称为“聚合”,结构表现为“部分-整体”形态,即通常所说的“is a part of”结构。 再者,对qybao(阿宝)所写代码(或称为设计)的补充。可以从两个方面进行合理地完善与扩展。 一、建议TProduct类为一虚基类(即包含虚方法或动态方法),然后根据不同的商品品种扩展其派生类。其好处对OO有些许了解的朋友应该都知道。 二、建议TStore类中不要直接拥有每个TProduct对象,而是拥有一个TProduct对象的列表,这样就可以整体上存储所有TProduct对象而在必要时又可以控制其中的每个对象元素了。。
根据 creativepeter(头皮屑) 意见整理,不知对否? type TProduct = class private FName :String; FPrice :Float; // protected // public procedure a ;virtual; procedure b ;virtual; .... //写一些虚方法,或抽象方法 published // end; type TPorduct1 = class(TProduct ) public procedure a ;override; //根据每个类的不同而继承
end;type TPorduct2 = class(TProduct ) //根据每个类的不同而继承 public procedure b ;override;
end;type TStore = class private FProduct :^TProduct; //这里我不太清楚是否这么写? // protected // public // published // end;
我觉得产品和库房虽然是有从属关系,但是不一定用对象包容关系来实现,虽然那样实现 更加OO,但是麻烦得很,要是你看过来自Borland的面向对象医院信息管理系统你就知道 要实现一个真正学术高度的OO系统有多么难,理解起来多费劲了,所以尽量避免类设计中嵌套对象. 以下设计中第一种设计方案用一个整数属性实现了从属关系,第二种方案用函数的参数的方式 实现了从属关系,如果要真正实现从属关系,那么必须写private FProduct: TProduct了,那样很 麻烦的,自己看着都头晕.//第一种修改建议: type TProduct = class private FName :String; FPrice :Float; FProductID: integer; //用一个ID代替Product对象 // protected // public property ProductID: integer read FProductID write FProductID;//添加产品ID属性 // //published//Published就面啦,毕竟不是要做组件,对组件作者没用 // end;type TStore = class private FProduct :TProduct; // protected // public procedure EnterStort(ProductID: integer); //这里通过ID调用产品对象,这样比较简单 procedure ExitStort(ProductID: integer); // //published//Published就面啦,毕竟不是要做组件,对组件作者没用 // end;//第二种修改建议(有点OO): type TProduct = class private FName :String; FPrice :Float; // protected // public // //published//Published就面啦,毕竟不是要做组件,对组件作者没用 // end;type TStore = class private FProduct :TProduct; // protected // public procedure EnterStort(Product: TProduct); //这里通过ID调用产品对象,这样比较简单 procedure ExitStort(Product: TProduct); // //published//Published就面啦,毕竟不是要做组件,对组件作者没用 // end; .... implementationTStore.EnterStort(Product: TProduct); begin if Product.FName = '香皂' and Product.FPrice < 2 then begin Product.Buy(); end; end;TStore.ExitStort(Product: TProduct); begin if Product.FPrice > 5 then begin Product.MakeMoney(); //发财啦!:) end; end;
要是你看过来自Borland的面向对象医院信息管理系统 // TO: man8888(北京男人) ( ) 哪裡可以看到呢 哥們。
对xjwy(程序春秋)作答之拾遗: 一、代码中不妥的部分: ①不知为何需要那么多的type关键字,只要在所有声明的类型的前面写一个type即可; ② TStore = class private FProduct : ^TProduct; //这里我不太清楚是否这么写? // protected // public // published // end; 这个FProduct : ^TProduct的声明不符我的作法,其实与本题提问者的写法相同。 ③ TPorduct1 = class(TProduct) public procedure a ;override; //根据每个类的不同而继承 ... end; procedure a ;override; {根据每个类的不同而继承←这个注解有问题,派生类不管有多少不同,只要继承同一基类,将继承其中所有数据成员、属性和方法成员等等,其自身没有选择余地,该注解应改为“根据每个类的不同而覆盖”。} ④ 一个容易被大家忽略的问题,就是Delphi里面没有float数据类型。 ⑤ TPorduct1、TPorduct2猜测不错的话是笔误吧,应该是TProduct1、TProduct2。 二、建议作法: 以下是我对该问题的一个解决方案(Delphi7 + Windows2000 Server测试通过),当然作为一个原型,有很多地方还值得雕琢。 建立一个新工程,保存主界面窗体及其单元文件,源代码如下: unit untMain;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, untBusiness;//untBusiness是接下来需要手动添加的一个单元文件type TMainForm = class(TForm) btnGenProduct: TButton; btnGenStore: TButton; procedure btnGenProductClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure btnGenStoreClick(Sender: TObject); private FStore : TStore; public { Public declarations } end;var MainForm: TMainForm;implementationconst ObjectInfo = 'Price of this Prodcut named %s is %8.2f';{$R *.dfm}procedure TMainForm.btnGenProductClick(Sender: TObject); var aProduct : TProduct; begin aProduct := TProduct1.Create; try aProduct.Name := 'AProduct1Obj'; aProduct.Price := 1.2; ShowMessage(Format(ObjectInfo, [aProduct.Name, aProduct.Price])); aProduct.a; aProduct.b; finally aProduct.Free; end; aProduct := TProduct2.Create; try aProduct.Name := 'AProduct2Obj'; aProduct.Price := 199.98; ShowMessage(Format(ObjectInfo, [aProduct.Name, aProduct.Price])); aProduct.a; aProduct.b; finally aProduct.Free; end; end;procedure TMainForm.FormCreate(Sender: TObject); begin FStore := TStore.Create; end;procedure TMainForm.FormDestroy(Sender: TObject); begin FStore.Free; end;procedure TMainForm.btnGenStoreClick(Sender: TObject); var aProduct : TProduct; begin aProduct := TProduct1.Create; aProduct.Name := 'AProduct1Obj'; aProduct.Price := 1.2; FStore.AddProduct(aProduct); end;end. 接下来,手动添加一个单元文件,源代码如下: unit untBusiness;interfaceuses SysUtils, Dialogs, Contnrs;type TProduct = class private FName : string; FPrice : Double; //将FPrice设为Double类型 function GetName : string; function GetPrice : Double; procedure SetName(Value : string); procedure SetPrice(Value : Double); public property Name : string read GetName write SetName; property Price : Double read GetPrice write SetPrice; constructor Create; procedure a;virtual; procedure b;virtual; end; TProduct1 = class(TProduct) public procedure a;override; //根据每个类的不同而覆盖 end; TProduct2 = class(TProduct) //根据每个类的不同而覆盖 public procedure b;override; end; TStore = class private FProductList : TObjectList; //使用TObjectList对象保存或移除仓库中的商品对象 function GetProductList: TObjectList; public constructor Create; destructor Destroy;override; property ProductList : TObjectList read GetProductList; procedure AddProduct(aProduct : TProduct); end;
const MessageText = 'This is a method called %s';implementation{ TProduct }procedure TProduct.a; begin ShowMessage(Format(MessageText, ['TProduct.a'])); end;procedure TProduct.b; begin ShowMessage(Format(MessageText, ['TProduct.b'])); end;constructor TProduct.Create; begin FName := 'AProduct'; FPrice := 0; ShowMessage(Format(MessageText, ['TProduct.Create'])); end;function TProduct.GetName: string; begin Result := FName; end;function TProduct.GetPrice: Double; begin Result := FPrice; end;procedure TProduct.SetName(Value: string); begin if Value <> FName then FName := Value; end;procedure TProduct.SetPrice(Value: Double); begin if Value <> FPrice then FPrice := Value; end;{ TProduct1 }procedure TProduct1.a; begin inherited; ShowMessage(Format(MessageText, ['TProduct1.a'])); end;{ TPorduct2 }procedure TProduct2.b; begin inherited; ShowMessage(Format(MessageText, ['TProduct1.b'])); end;{ TStore }procedure TStore.AddProduct(aProduct: TProduct); begin FProductList.Add(aProduct); ShowMessage('A Product has been added!'); end;constructor TStore.Create; begin FProductList := TObjectList.Create; FProductList.OwnsObjects := True; //使FProductList在销毁时自动销毁其下拥有的对象 end;destructor TStore.Destroy; begin FProductList.Free; inherited; end;function TStore.GetProductList: TObjectList; begin Result := FProductList; end;end. 有些比较重要的地方我做了注解,其余部分请自行研究,不妥之处请指正。
TProduct = class
private
FName :String;
FPrice :Float;
//
protected
//
public
//
published
//
end;type
TStore = class
private
FProduct :TProduct; //这里就是仓库拥有商品
//
protected
//
public
//
published
//
end;
一、建议TProduct类为一虚基类(即包含虚方法或动态方法),然后根据不同的商品品种扩展其派生类。其好处对OO有些许了解的朋友应该都知道。
二、建议TStore类中不要直接拥有每个TProduct对象,而是拥有一个TProduct对象的列表,这样就可以整体上存储所有TProduct对象而在必要时又可以控制其中的每个对象元素了。。
type
TProduct = class
private
FName :String;
FPrice :Float;
//
protected
//
public
procedure a ;virtual;
procedure b ;virtual;
.... //写一些虚方法,或抽象方法
published
//
end;
type
TPorduct1 = class(TProduct )
public
procedure a ;override; //根据每个类的不同而继承
end;type
TPorduct2 = class(TProduct ) //根据每个类的不同而继承
public
procedure b ;override;
end;type
TStore = class
private
FProduct :^TProduct; //这里我不太清楚是否这么写?
//
protected
//
public
//
published
//
end;
更加OO,但是麻烦得很,要是你看过来自Borland的面向对象医院信息管理系统你就知道
要实现一个真正学术高度的OO系统有多么难,理解起来多费劲了,所以尽量避免类设计中嵌套对象.
以下设计中第一种设计方案用一个整数属性实现了从属关系,第二种方案用函数的参数的方式
实现了从属关系,如果要真正实现从属关系,那么必须写private FProduct: TProduct了,那样很
麻烦的,自己看着都头晕.//第一种修改建议:
type
TProduct = class
private
FName :String;
FPrice :Float;
FProductID: integer; //用一个ID代替Product对象
//
protected
//
public
property ProductID: integer read FProductID write FProductID;//添加产品ID属性
//
//published//Published就面啦,毕竟不是要做组件,对组件作者没用
//
end;type
TStore = class
private
FProduct :TProduct;
//
protected
//
public
procedure EnterStort(ProductID: integer); //这里通过ID调用产品对象,这样比较简单
procedure ExitStort(ProductID: integer);
//
//published//Published就面啦,毕竟不是要做组件,对组件作者没用
//
end;//第二种修改建议(有点OO):
type
TProduct = class
private
FName :String;
FPrice :Float;
//
protected
//
public
//
//published//Published就面啦,毕竟不是要做组件,对组件作者没用
//
end;type
TStore = class
private
FProduct :TProduct;
//
protected
//
public
procedure EnterStort(Product: TProduct); //这里通过ID调用产品对象,这样比较简单
procedure ExitStort(Product: TProduct);
//
//published//Published就面啦,毕竟不是要做组件,对组件作者没用
//
end;
....
implementationTStore.EnterStort(Product: TProduct);
begin
if Product.FName = '香皂' and Product.FPrice < 2 then
begin
Product.Buy();
end;
end;TStore.ExitStort(Product: TProduct);
begin
if Product.FPrice > 5 then
begin
Product.MakeMoney(); //发财啦!:)
end;
end;
...
end;
TProducts = class(TCollect)
...
end;
TStock = class
private
FProducts: TProducts;
end;
// TO: man8888(北京男人) ( )
哪裡可以看到呢 哥們。
一、代码中不妥的部分:
①不知为何需要那么多的type关键字,只要在所有声明的类型的前面写一个type即可;
②
TStore = class
private
FProduct : ^TProduct; //这里我不太清楚是否这么写?
//
protected
//
public
//
published
//
end;
这个FProduct : ^TProduct的声明不符我的作法,其实与本题提问者的写法相同。
③
TPorduct1 = class(TProduct)
public
procedure a ;override; //根据每个类的不同而继承
...
end;
procedure a ;override;
{根据每个类的不同而继承←这个注解有问题,派生类不管有多少不同,只要继承同一基类,将继承其中所有数据成员、属性和方法成员等等,其自身没有选择余地,该注解应改为“根据每个类的不同而覆盖”。}
④
一个容易被大家忽略的问题,就是Delphi里面没有float数据类型。
⑤
TPorduct1、TPorduct2猜测不错的话是笔误吧,应该是TProduct1、TProduct2。
二、建议作法:
以下是我对该问题的一个解决方案(Delphi7 + Windows2000 Server测试通过),当然作为一个原型,有很多地方还值得雕琢。
建立一个新工程,保存主界面窗体及其单元文件,源代码如下:
unit untMain;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, untBusiness;//untBusiness是接下来需要手动添加的一个单元文件type
TMainForm = class(TForm)
btnGenProduct: TButton;
btnGenStore: TButton;
procedure btnGenProductClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnGenStoreClick(Sender: TObject);
private
FStore : TStore;
public
{ Public declarations }
end;var
MainForm: TMainForm;implementationconst
ObjectInfo = 'Price of this Prodcut named %s is %8.2f';{$R *.dfm}procedure TMainForm.btnGenProductClick(Sender: TObject);
var
aProduct : TProduct;
begin
aProduct := TProduct1.Create;
try
aProduct.Name := 'AProduct1Obj';
aProduct.Price := 1.2;
ShowMessage(Format(ObjectInfo, [aProduct.Name, aProduct.Price]));
aProduct.a;
aProduct.b;
finally
aProduct.Free;
end;
aProduct := TProduct2.Create;
try
aProduct.Name := 'AProduct2Obj';
aProduct.Price := 199.98;
ShowMessage(Format(ObjectInfo, [aProduct.Name, aProduct.Price]));
aProduct.a;
aProduct.b;
finally
aProduct.Free;
end;
end;procedure TMainForm.FormCreate(Sender: TObject);
begin
FStore := TStore.Create;
end;procedure TMainForm.FormDestroy(Sender: TObject);
begin
FStore.Free;
end;procedure TMainForm.btnGenStoreClick(Sender: TObject);
var
aProduct : TProduct;
begin
aProduct := TProduct1.Create;
aProduct.Name := 'AProduct1Obj';
aProduct.Price := 1.2;
FStore.AddProduct(aProduct);
end;end. 接下来,手动添加一个单元文件,源代码如下:
unit untBusiness;interfaceuses
SysUtils, Dialogs, Contnrs;type
TProduct = class
private
FName : string;
FPrice : Double; //将FPrice设为Double类型
function GetName : string;
function GetPrice : Double;
procedure SetName(Value : string);
procedure SetPrice(Value : Double);
public
property Name : string read GetName write SetName;
property Price : Double read GetPrice write SetPrice;
constructor Create;
procedure a;virtual;
procedure b;virtual;
end;
TProduct1 = class(TProduct)
public
procedure a;override; //根据每个类的不同而覆盖
end;
TProduct2 = class(TProduct) //根据每个类的不同而覆盖
public
procedure b;override;
end;
TStore = class
private
FProductList : TObjectList; //使用TObjectList对象保存或移除仓库中的商品对象
function GetProductList: TObjectList;
public
constructor Create;
destructor Destroy;override;
property ProductList : TObjectList read GetProductList;
procedure AddProduct(aProduct : TProduct);
end;
const
MessageText = 'This is a method called %s';implementation{ TProduct }procedure TProduct.a;
begin
ShowMessage(Format(MessageText, ['TProduct.a']));
end;procedure TProduct.b;
begin
ShowMessage(Format(MessageText, ['TProduct.b']));
end;constructor TProduct.Create;
begin
FName := 'AProduct';
FPrice := 0;
ShowMessage(Format(MessageText, ['TProduct.Create']));
end;function TProduct.GetName: string;
begin
Result := FName;
end;function TProduct.GetPrice: Double;
begin
Result := FPrice;
end;procedure TProduct.SetName(Value: string);
begin
if Value <> FName then
FName := Value;
end;procedure TProduct.SetPrice(Value: Double);
begin
if Value <> FPrice then
FPrice := Value;
end;{ TProduct1 }procedure TProduct1.a;
begin
inherited;
ShowMessage(Format(MessageText, ['TProduct1.a']));
end;{ TPorduct2 }procedure TProduct2.b;
begin
inherited;
ShowMessage(Format(MessageText, ['TProduct1.b']));
end;{ TStore }procedure TStore.AddProduct(aProduct: TProduct);
begin
FProductList.Add(aProduct);
ShowMessage('A Product has been added!');
end;constructor TStore.Create;
begin
FProductList := TObjectList.Create;
FProductList.OwnsObjects := True; //使FProductList在销毁时自动销毁其下拥有的对象
end;destructor TStore.Destroy;
begin
FProductList.Free;
inherited;
end;function TStore.GetProductList: TObjectList;
begin
Result := FProductList;
end;end.
有些比较重要的地方我做了注解,其余部分请自行研究,不妥之处请指正。
回复人: creativepeter(头皮屑) ( ) 信誉:100 2005-02-22 16:24:00 得分: 0
干到2:00
写出来了,测试通过。
哪有空间我贴个MM的图。
还请qufo (1)(飞)(如果后面没有出现<%Script,则表示入侵成功) 兄早日结帖,以免夜长梦多:-)。
贴MM图看得比较清楚嘛。
http://blog.csdn.net/qufo/archive/2005/02/26/302591.aspx
自己看。