本人才疏学浅,对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.   

    搂主是写好一写模板然后不段调用模板的么?!..层层调用,比如;
    1层: 空的form窗体 RootForm
    2层: 从 RootForm继承, 具体实现为: InputForm
    3层; 从BsseInputForm继承, 加入但表录入项目 BaseInputForm
    4层: 主从表录入模板: UoinImputform...   我是小程序员,楼主明白的东西对我还是困惑,搂住运用OOP基于TFrame来创建不同的模块,能否给出些具体的类或者代码呢?!谢谢!
      
      顶一下 ..
      

  2.   

    我怕代码粘贴出来太长了!会影响大家的兴趣!unit UState;interfaceuses
      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.
      

  3.   

    上面的是基类,下面的是基于这个基类所创建出来的类似于TListView控件中的TItem的东西:{显示房间资料:
    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.
      

  4.   

    上面是有关Item的东西,下面是容纳这些东西的容器:unit UShowState;interfaceuses
      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;
      

  5.   

    surpassable() ( ) 说得对,我的目标就是这样嘛!其实数据库很多功能基本上是差不多的,具体用户的业务不同,但是我感觉真的有很多东西都可以重复利用!但是没什么人发表见解!不知道是什么原因!
      

  6.   

    永远爱着一个叫"傲"的女孩
    csdn这类名字咋这么多捏?
    OOP我不会啊,惭愧~
      

  7.   

    一些对象的创建问题,我不懂怎么去create(参数1,参数2,参数3,参数4............)我不知道这个怎么去实现,我每次都是create完以后执行一个过程去实现初始化,感觉这个是最大的缺点,可能不叫缺点了,而叫根本不懂什么是OOP了!我也感觉是这样,究竟我的create怎么去定义?我是该重载,还是覆盖?还是执行完父类后执行自己的create过程(就像inherited;实现一样)?---------------------
    這也算是一種方法 這樣可以避免你;e構造函數如果出現異常;e情況 在構造函數出現異常是很糟糕;e事情;e 因為編譯器在構造函數種為我們設定了很多 比如vmt ;mt 而專門使用一個init函數則不會出現此類情況 或者說 如果出現其它異常處理起來也方便Σ ;uo...一般 我;e 大部分是 覆蓋还是执行完父类后执行自己的create过程(就像inherited;实现一样)?
    ---------------------
    這個是要看你;e具體實現了 恩 我;e 鍵盤還是輸入法出問題了 有些鍵出問題了。。不好;a字 先說這些。。---------------------
    樓主 好樣Σ 就是要善於思考 :)
      

  8.   

    其实现在有现成的已经可用的经验了
    在这方面的技术已经成熟了
    先看以下刘艺的《DELPHI面向对象编程》
    然后看一下他的关于模式的那本书
    也就可以了
      

  9.   

    oop我觉得就是把能封装起来的都装起来,而且分类要做好,函数、方法、参数、常量、变量能做成类的就做成类的形式,可能开始的时候设计比较费时,但使用起来的时候就会发现那些前期的事情真的没有白费,没有任何重复的代码;没有令人郁闷的复制粘贴。而且这样写出的东西,想要修改的时候,直接修改类的内容就可以了,对象是对类的实例化,维护修改起来好方便。
    oop是个好东西!!!有镐头!!!
      

  10.   

    首先我来回答一下我这段时间来对我自己的问题的一些回答:
    1:可能是因为需要吧,那些Item内容太多了,所以那些动态创建的对象创建起来比较慢,同时使用的是TList而不是数组,CPU慢的,还会导致死机。哎,老板要求这样做,我也没办法哦!
    2:
    重载Create函数的方法,制作自己的Create方法
      public
        { Public declarations }
        Constructor Create(Text:string); reintroduce ; overload;
    3:
    对象被创建后所做的初始化使用的方法
      protected
        procedure Loaded; override;上面的都可以实现初始化,可以满足我的需要,哎!这么晚才知道,主要是缺乏交流啊!晕!呆不下去了!再这样,自己的发展太慢了!
    4:基本上都不想放在datamodal模块了!处理起来,有时候会影响过多的模块!还是每一个模块里面采用各自独立所需要的数据库控件好了!
      

  11.   


    OOP 基本上知道。什么时候能把 OO 用到设计上就好了