本人才疏学浅,对OOP理解的不是很深,想请教各位或者大家交流一些OOP这种东西的用法或者经验.请各位指点一二!谢谢!我...我运用OOP一般都是基于TFrame来创建不同的模块!还有就是基于TFrom的.对于一些具有特定功能的东西做成一个继承自TFrame,或者是继承自TFrom这样的方式去实现.目前做过以下一些模块:
1:数据库的动态连接:(继承TFrom),功能:运行的时候发现数据库连接字符串不对,显示窗体让客户输入必要的信息,产生新的连接字符串,保存到ini文件里面.
2:权限动态设置:(继承TFrom),功能:根据一个TMainMenu控件,动态设置这些TMainMenu的enable属性,要是这些TMainMenu控件是使用了某个TAction的,同时也会设置这些TAction的可用属性.缺点(要是设置了权限以后,当TMainMenu改变以后,权限的一一对应就会失效,但是重新设置权限就可以再次应用到新的Tmainmenu.)
3:类似TListView控件的那种:TListView对应的Item就是我的:TZState = class(TFrame),放置这些TZState的就是:TZShowState = class(TFrame).其它的一些就是根据工程的不同,项目的不同,为了实现某种某种固定的功能而设计的模块,都采用了继承TFrame,在不同的窗体模块中要是需要用到这些模块,大家可以使用Frames控件往From里面添加的.我认为自己不足的地方太多了,没意识到,意识到的地方有:
1:类似TListView控件的这种,不懂怎么把Item和ShowState很好的结合.老是感觉有什么不对劲的地方,而且速度处理起来比TListView慢很多!数据量一大,就更慢了!
2:一些对象的创建问题,我不懂怎么去create(参数1,参数2,参数3,参数4............)我不知道这个怎么去实现,我每次都是create完以后执行一个过程去实现初始化,感觉这个是最大的缺点,可能不叫缺点了,而叫根本不懂什么是OOP了!我也感觉是这样,究竟我的create怎么去定义?我是该重载,还是覆盖?还是执行完父类后执行自己的create过程(就像inherited;实现一样)?
3:某些类的初始化的值不知道怎么弄,就好像全局变量,我怎么让某个全局变量有一个初始值?不是程序调用,是编译的时候就存在的.
4:感觉TDataModule的使用有点问题,不应该把一个项目中的所有表啊,存储过程啊,查询啊都放那里,感觉应该是把他们分放到各自的模块里面去,毕竟有些东西是动态创建的,有些表或者查询共用了,会有考虑不到的情况出现.所以还是放到用到他们的模块里面,连接字符串就肯定是使用TDataModule里面的connection了.(如果有人说,都放在TDataModule里面,可以集中对数据进行处理啊!确实是这样的,放在一个TDataModule的话,可以集中处理数据的操作,所以这个得讨论一下.我感觉,这些数据不是是分散的数据,从OOP的角度来说,数据是属于某个对象的,而不属于一个数据整体,要是把TDataModule认为就是一个数据源,那么就是另外考虑,这个我很模糊!)
5:好像暂时没发现什么了!上面这些呢,是我历时大概有7~8个月的使用Delphi的结果吧,是个人独自通过大家一直以来的帮助与总结的结果,工作是一个人,一个人在公司开发项目工程.包括数据库的设计,代码的编写,调试,去客户那服务,所以见识面太狭窄了,导致有上面的可能是很多人认为的畸形吧!项目就做过2个,1个是收水费的,现在这个是一个休闲中心的.第一个已经给客户用了,第二个还没真正完成!基本功能实现了!恩!谢谢大家能看到这里!谢谢!
下面是大家不要吝啬的心得拿出来吧!哈哈!
1:数据库的动态连接:(继承TFrom),功能:运行的时候发现数据库连接字符串不对,显示窗体让客户输入必要的信息,产生新的连接字符串,保存到ini文件里面.
2:权限动态设置:(继承TFrom),功能:根据一个TMainMenu控件,动态设置这些TMainMenu的enable属性,要是这些TMainMenu控件是使用了某个TAction的,同时也会设置这些TAction的可用属性.缺点(要是设置了权限以后,当TMainMenu改变以后,权限的一一对应就会失效,但是重新设置权限就可以再次应用到新的Tmainmenu.)
3:类似TListView控件的那种:TListView对应的Item就是我的:TZState = class(TFrame),放置这些TZState的就是:TZShowState = class(TFrame).其它的一些就是根据工程的不同,项目的不同,为了实现某种某种固定的功能而设计的模块,都采用了继承TFrame,在不同的窗体模块中要是需要用到这些模块,大家可以使用Frames控件往From里面添加的.我认为自己不足的地方太多了,没意识到,意识到的地方有:
1:类似TListView控件的这种,不懂怎么把Item和ShowState很好的结合.老是感觉有什么不对劲的地方,而且速度处理起来比TListView慢很多!数据量一大,就更慢了!
2:一些对象的创建问题,我不懂怎么去create(参数1,参数2,参数3,参数4............)我不知道这个怎么去实现,我每次都是create完以后执行一个过程去实现初始化,感觉这个是最大的缺点,可能不叫缺点了,而叫根本不懂什么是OOP了!我也感觉是这样,究竟我的create怎么去定义?我是该重载,还是覆盖?还是执行完父类后执行自己的create过程(就像inherited;实现一样)?
3:某些类的初始化的值不知道怎么弄,就好像全局变量,我怎么让某个全局变量有一个初始值?不是程序调用,是编译的时候就存在的.
4:感觉TDataModule的使用有点问题,不应该把一个项目中的所有表啊,存储过程啊,查询啊都放那里,感觉应该是把他们分放到各自的模块里面去,毕竟有些东西是动态创建的,有些表或者查询共用了,会有考虑不到的情况出现.所以还是放到用到他们的模块里面,连接字符串就肯定是使用TDataModule里面的connection了.(如果有人说,都放在TDataModule里面,可以集中对数据进行处理啊!确实是这样的,放在一个TDataModule的话,可以集中处理数据的操作,所以这个得讨论一下.我感觉,这些数据不是是分散的数据,从OOP的角度来说,数据是属于某个对象的,而不属于一个数据整体,要是把TDataModule认为就是一个数据源,那么就是另外考虑,这个我很模糊!)
5:好像暂时没发现什么了!上面这些呢,是我历时大概有7~8个月的使用Delphi的结果吧,是个人独自通过大家一直以来的帮助与总结的结果,工作是一个人,一个人在公司开发项目工程.包括数据库的设计,代码的编写,调试,去客户那服务,所以见识面太狭窄了,导致有上面的可能是很多人认为的畸形吧!项目就做过2个,1个是收水费的,现在这个是一个休闲中心的.第一个已经给客户用了,第二个还没真正完成!基本功能实现了!恩!谢谢大家能看到这里!谢谢!
下面是大家不要吝啬的心得拿出来吧!哈哈!
1层: 空的form窗体 RootForm
2层: 从 RootForm继承, 具体实现为: InputForm
3层; 从BsseInputForm继承, 加入但表录入项目 BaseInputForm
4层: 主从表录入模板: UoinImputform... 我是小程序员,楼主明白的东西对我还是困惑,搂住运用OOP基于TFrame来创建不同的模块,能否给出些具体的类或者代码呢?!谢谢!
顶一下 ..
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, RzPanel;
type
TSelectEvent = procedure(Sender: TObject;Selected: Boolean) of object;
TZState = class(TFrame)
P_Con: TRzPanel;
procedure FrameMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
FSelected:boolean;//当前控件被选择
FSelect: TSelectEvent; protected
procedure DoSelect;
function Getselected:boolean;
procedure setselected(value:boolean);
function GetState:integer;virtual; abstract;
public
{ Public declarations }
property Selected:boolean read GetSelected write SetSelected default false;
property OnSelected: TSelectEvent read FSelect write FSelect;
property State:integer read GetState;
end;
implementation
uses
RzCommon;
{$R *.dfm}
procedure TZState.DOSelect;
begin
(* if your event isn't assigned in the client, the FChange field will be nil.
it is a prerequisite in events programming to check wether something is
nil before calling on it. *)
(*如果你的事件没有分派到客户里面,那么Fchange将会被赋值为nil
在呼叫访问它之前检测某些事物是否是nil那是必须做的事.
*)
if Assigned(FSelect) then
Fselect(Self,selected);
if selected then
begin
p_con.Borderouter:=fsPopup;
p_con.BorderInner:=fspopup;
p_con.BorderHighlight:=clLime;//$00E0CC66;
p_con.Bordershadow:=clLime//$00E0CC66;
end
else
begin
p_con.Borderouter:=fsnone;
p_con.BorderInner:=fsnone;
p_con.BorderHighlight:=clBtnShadow;
p_con.Bordershadow:=clBtnShadow;
end;
end;procedure TZState.FrameMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
//处理被选择的效果
if button=mbRight then
begin
if not selected then
selected:=true;
end;
if button=mbleft then
selected:=not selected;
end;
function TZState.Getselected:boolean;
begin
result:=Fselected;
end;
procedure TZState.setselected(value:boolean);
begin
Fselected:=value;
// update; //强行重绘控件
doselect;
end;end.
1:房间名称
2:匙牌的组
3:当前在该房间的匙牌
4:当前在该房间的员工
5:当前房间的剩余时间
}
unit URom;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, UState, ExtCtrls, RzPanel, StdCtrls, RzLabel, RzStatus;type
TZRom = class(TZState)
Time: TRzClockStatus;
R_Name: TRzGroupBox;
Key: TRzLabel;
Worker: TRzLabel;
private
{ Private declarations }
E_Time:Tdatetime; //预结束时间
R_State,R_Team:integer; //数据库中的状态和数据库中的组编号
procedure StateControl(state:integer);
procedure setTeam(value:integer);
function GetTeam:integer;
protected
function GetState:integer;override;
public
{ Public declarations }
procedure init(RomName,Keyname,EMNO:string;EndTime:Tdatetime;ST,STeam:integer);overload;
procedure init(RomName,Keyname,EMNO:string;ST,STeam:integer);overload;
procedure TimeGetDateTime(Sender: TObject; var DateTime: TDateTime); property Team:integer read GetTeam write SetTeam;
end;
implementation
uses
DateUtils,UShowState, DMUnit;
{$R *.dfm}procedure TZRom.init(RomName,Keyname,EMNO:string;EndTime:Tdatetime;ST,STeam:integer);
// 房间名称 匙牌名称,员工编号组,预结束时间 状态值,组编号
begin
//初始化设置初始化信息 init(RomName,Keyname,EMNO,ST,STeam);
E_Time:=EndTime;
time.Tag:=1;end;
procedure TZRom.init(RomName,Keyname,EMNO:string;ST,STeam:integer);
var
strTeam:string;
begin
//初始化设置初始化信息
team:=Steam;
case Team of
-1:strTeam:='';
0:strTeam:='--单';
else
strTeam:='-组'+inttostr(Steam);
end; R_Name.Caption:='房:'+Romname+strTeam;
key.Caption:='匙:'+keyname;
Worker.Caption:='工:'+EMNO;
time.Tag:=4;
time.OnGetDateTime:=TimeGetDateTime;
R_State:=ST;
end;function TZRom.GetState:integer;
begin//返回当前控件状态
result:=R_state;
end;
function TZRom.GetTeam:integer;
begin//返回当组编号
result:=R_Team;
end;
procedure TZRom.setTeam(value:integer);
begin
R_Team:=value;
end;
procedure TZRom.TimeGetDateTime(Sender: TObject; var DateTime: TDateTime);
begin
if time.Tag=4 then //预结束时间为NULL
begin
datetime:=now-now;
statecontrol(R_state);
end
else
begin
datetime:=E_Time-Now;
// 超时
if R_state=1 then
begin
if now>e_time then
statecontrol(6)
else if now<e_time then
begin
//设置催钟倒计时的倒数
if now>IncMinute(E_Time,-5) then
statecontrol(5)
else
statecontrol(1);
end;
end;
IF r_state=4 then
begin
statecontrol(4);
end;
end;
end;
procedure TZRom.StateControl(state:integer);
//状态处理,根据state传递过来的状态编号进行相关处理
var
MyColor:TColor;
i:integer;
begin mycolor:=dm.GetStateColor(dm.romstate,state);
P_Con.Color:=MyColor;
R_Name.Color:=MyColor;
time.FillColor:=MyColor;
R_state:=state;
end;
end.
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, RzTabs, ExtCtrls, RzPanel, DB, ADODB, Menus,UState;type
//定义选择小item事件
TSelectItemEvent=procedure (Sender: TObject; Item: TZState;Selected: Boolean;NewIndex,OldIndex:integer) of object;
TZShowState = class(TFrame)
P_All: TRzPanel;
Page: TRzPageControl;
TabSheet1: TRzTabSheet;
P_State: TRzPanel;
Mydata: TADOQuery;
PM: TPopupMenu;
T: TTimer;
procedure FrameResize(Sender: TObject);
procedure MydataAfterOpen(DataSet: TDataSet);
procedure TTimer(Sender: TObject); private
{ Private declarations }
FSelectItem:TSelectItemEvent;
Findex:integer;
FMultiSelect:boolean;
function GetIndex:integer;
procedure setIndex(value:integer);
function GetMultiSelect:boolean;
procedure setMultiselect(value:boolean); protected procedure PaiLieAll; //排列所有item
procedure updateAllstates; //更新所有item数据
procedure DoSelectItem(Sender:TZState;Selected: Boolean); //执行被选择的事件
procedure MakeStates; //虚函数,制作每一个item
procedure updateState(i:integer);virtual;abstract; //更新item[i]
procedure makestate(i:integer);virtual;abstract; public
{ Public declarations }
mystates:array of TZState;
MySheets:array of TRzTabSheet;
//事件:被选择的事件
property OnSelectItem: TSelectItemEvent read FSelectItem write FSelectItem;
procedure MyStatesSelected(Sender:TObject;Selected: Boolean);
property ItemIndex:integer read GetIndex write setIndex default -1;
property MultiSelect:boolean read GetMultiSelect write setMultiSelect default false;
//更新所有item
procedure reshow;
end;implementation{$R *.dfm}
procedure TZShowState.DoSelectItem(Sender:TZState;Selected: Boolean);
var
i:integer;
begin
//item选择的时候所要做的事情
//下面是进行了item 选择以后的操作 for i:=low(mystates) to high(mystates) do
if mystates[i]=sender then
begin
(*如果你的事件没有分派到客户里面,那么对象FSelectItem的事件将会被赋值为nil
在呼叫访问它之前检测该事务事物的这个事件是否是nil那是必须做的事.
*)
if Assigned(FSelectItem) then
// 自身 被选择的item,是否被选择,旧的itemindex
FselectItem(Self,sender,selected,i,itemindex);
itemindex:=i;
mydata.RecNo:=i+1;
break;
end; if MultiSelect=false then
begin //不能多选
for i:=low(mystates) to high(mystates) do
begin
if (mystates[i]<>sender) and (mystates[i].Selected=true) then
mystates[i].Selected:=false;
end;
end;end;
procedure TZShowState.MyStatesSelected(Sender:TObject;Selected: Boolean);
begin
//item被选择的事件
if selected then
begin
itemindex:=-1;
doSelectItem(TZState(Sender),TZState(sender).Selected);
end;
end;function TZShowState.GetIndex:integer;
begin
//获取当前被选择的小房间
if Findex>=0 then
begin
if not mystates[Findex].Selected then
result:=-1
else
result:=Findex;
end
else
result:=Findex;
end;
procedure TZShowState.setIndex(value:integer);
begin
//设置当前的index
findex:=value;
end;function TZShowState.GetMultiselect:boolean;
begin
//获取当前被选择的小房间
result:=FMultiselect;
end;
procedure TZShowState.setMultiselect(value:boolean);
begin
//设置能否多选
FMultiselect:=value;
end;procedure TZShowState.PaiLieAll;
//排列所有已创建的房间对象
var
//onePage:TRzTabSheet;
PCount,i,j,PerCount,CC,RC,CD,RD:integer;
//PCount页数,i,j:中间变量,
//PerCount每页能容纳多少个控件,CC:列数量,RC:行数量
//CD:列间隔,RD:行间隔
begin
if length(mystates)=0 then exit;//计算控件能容纳多少个控件
CC:=page.Pages[0].Width div mystates[0].Width;
RC:=page.Pages[0].Height div mystates[0].Height;
PerCount:=CC*RC;
//计算列间距和行间距
CD:=(page.Pages[0].Width mod mystates[0].Width) div CC;
RD:=(page.Pages[0].Height mod mystates[0].Height) div RC;
//计算页数 if (length(mystates) mod PerCount)=0 then
pCount:=length(mystates) div percount
else
pCount:=length(mystates) div percount+1;//为防止页数的改变而产生剩余时间控件的父亲不存在,因此改变他们的所有父亲
for i:=low(mystates) to high(mystates) do
begin
mystates[i].Parent:=page.Pages[0];
end;
//释放所有页控件
{
if length(mysheet)>0 then
begin
for i:=high(mysheet) to low(mysheet) do
begin
mysheet[i].Free;
end;
setlength(mysheet,0);
end;
}
//使用上面语句会出现问题:page的pages会没有完全释放掉,如果使用下面的语句不会出现刚才所说的问题
if page.PageCount>1 then
begin
for i:=1 to page.PageCount-1 do
{
这里必须是1,如果不是1而是i会出错(超出下标范围,
因为在释放以后page控件的页数就减1,因此出现3页开始,
每释放掉一页它的页数就改变了,所以出现超出下标)
}
page.Pages[1].Free;
csdn这类名字咋这么多捏?
OOP我不会啊,惭愧~
這也算是一種方法 這樣可以避免你;e構造函數如果出現異常;e情況 在構造函數出現異常是很糟糕;e事情;e 因為編譯器在構造函數種為我們設定了很多 比如vmt ;mt 而專門使用一個init函數則不會出現此類情況 或者說 如果出現其它異常處理起來也方便Σ ;uo...一般 我;e 大部分是 覆蓋还是执行完父类后执行自己的create过程(就像inherited;实现一样)?
---------------------
這個是要看你;e具體實現了 恩 我;e 鍵盤還是輸入法出問題了 有些鍵出問題了。。不好;a字 先說這些。。---------------------
樓主 好樣Σ 就是要善於思考 :)
在这方面的技术已经成熟了
先看以下刘艺的《DELPHI面向对象编程》
然后看一下他的关于模式的那本书
也就可以了
oop是个好东西!!!有镐头!!!
1:可能是因为需要吧,那些Item内容太多了,所以那些动态创建的对象创建起来比较慢,同时使用的是TList而不是数组,CPU慢的,还会导致死机。哎,老板要求这样做,我也没办法哦!
2:
重载Create函数的方法,制作自己的Create方法
public
{ Public declarations }
Constructor Create(Text:string); reintroduce ; overload;
3:
对象被创建后所做的初始化使用的方法
protected
procedure Loaded; override;上面的都可以实现初始化,可以满足我的需要,哎!这么晚才知道,主要是缺乏交流啊!晕!呆不下去了!再这样,自己的发展太慢了!
4:基本上都不想放在datamodal模块了!处理起来,有时候会影响过多的模块!还是每一个模块里面采用各自独立所需要的数据库控件好了!
OOP 基本上知道。什么时候能把 OO 用到设计上就好了