Newsgroup: it.comp.lang.delphi
Titolo: Ancora sulle classi

Sotto riporto il codice della classe che ho definito. In effetti, questa 
classe non include tutta una serie di dati (inerenti quello che la classe 
rappresenta, un budget), che nella elaborazione mi servono solo 
saltuariamente, ma la cui fonte è la setssa, e cioè un record di un dataset 
o l'input dell'utente. Pensando a cosa fare, vedo che ci sono molte 
possibile alternative da cui non riesco a districarmi:
- Ridefinire la classe sotto descritta aggiungendo questi dati; questo 
sarebbe semplice. Oppure:
- creare un'altra classe che raccolga solo questi dati e di cui la prima 
sarebe una derivata: ma in questo caso dovrei creare una istanza di entrambe 
quando avessi bisogno di entrambe le serie di dati ?
- etc. etc.
Cosa è consigliabile fare ? Lo so che non conoscete le mie esigenze, ma 
prendetelo, come me, come un esercizio per capire...
 
unit MensiliBU;
{ Classe TMensiliB che rappresenta i valori (in formato stringa)
  dei budget mensili di una Categoria per un determinato anno
  I valori vengono assunti dai parametri passati nella proc FillRecFromDB
  che il chiamante reperisce dal record Budget con chiave Anno+Cat}
interface
uses
 Windows, SysUtils, Classes, Graphics, Controls,
  StdCtrls, DBCtrls, Db, DBTables, Dialogs;
type
  TMensiliB = class
  private
    FAnno: string;
    FCat: string;
    FMensiliB: TStringList;
  public
    property MensiliB: TStringList read FMensiliB;
    constructor Create; virtual;
    destructor Destroy; override;
    procedure Fill(aAnno,aCat: string; 
a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12: integer);
    function  GetMensiliB: TStringList;
    function  GetCat: string;
end;
implementation
 
constructor TMensiliB.Create;
begin
   FMensiliB:= TStringList.Create;
   inherited Create;
end;
 
destructor TMensiliB.Destroy;
begin
   FMensiliB.Free;
   Inherited Destroy;
end;
 
procedure TMensiliB.Fill(aAnno,aCat: string; 
a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12: integer);
var
  tot: integer;
 begin
   tot:= 0;
   tot:= a01;
   tot:= tot + a02-a01;
   tot:= tot + a03-a02;
   tot:= tot + a04-a03;
   tot:= tot + a05-a04;
   tot:= tot + a06-a05;
   tot:= tot + a07-a06;
   tot:= tot + a08-a07;
   tot:= tot + a09-a08;
   tot:= tot + a10-a09;
   tot:= tot + a11-a10;
   tot:= tot + a12-a11;
   FMensiliB.Add(inttostr(a01));
   FMensiliB.Add(inttostr(a02-a01));
   FMensiliB.Add(inttostr(a03-a02));
   FMensiliB.Add(inttostr(a04-a03));
   FMensiliB.Add(inttostr(a05-a04));
   FMensiliB.Add(inttostr(a06-a05));
   FMensiliB.Add(inttostr(a07-a06));
   FMensiliB.Add(inttostr(a08-a07));
   FMensiliB.Add(inttostr(a09-a08));
   FMensiliB.Add(inttostr(a10-a09));
   FMensiliB.Add(inttostr(a11-a10));
   FMensiliB.Add(inttostr(a12-a11));
   FMensiliB.Add(inttostr(tot));
end;
 
function TMensiliB.GetMensiliB: TStringList;
begin
   result:= FMensiliB;
end;
end. 
 

Cosi su due piedi...
 
 
 io definirei una classe che eredita dalla prima ed espone quanto serve sporadicamente. Non devi istanziarne 2...xche dovresti?
O usi quella base o usi quella "potenziata".
 
A parte cio':
 
perdonami, ma trovo le tue nomenclature cinofalliche.
 
Cosa vuol dire MensiliB?
Cosa vuol dire Cat?
Cosa Vuol dire a01, a02 etc?
Manca qualcosa per leggere un valore tra a01, a02 etc
Ad ogni chiamata al metodo fill avreo 13 righe in piu.
Il costruttore va dichiarato override e non virtual.
Non e' una buona idea avere la 1a riga del costruttore che non sia inherited create.
 
A.


Supponi che io faccia qualcosa come segue (la butto giù qui, semplificando):
Type
  TBudget  = class
    Anno   : string;
    mm     : integer;
    id     : string;
    Conto  : string;
    Sot    : string;
    Gruppo : string;
    Descri : string;
    ----------- etc. etc.
    procedure Create(aAnno:string;aMM:integer;aID,aConto,...etc. etc.  );
  end;
procedure Create(aAnno:string;aMM:integer;aID,aConto, .....etc. etc.  );
begin
    Anno     := aAnno;
    mm       := aMM;
    id       := aID;
    Conto    := aConto;
    Sot      := aSot;
    Gruppo   := aGruppo;
    Descri   := aDescri;
    ...............
end;
 
Dovrei ridefinire la mia originaria classe così:
  TMensiliB = class(TBudget)
e cambiare anche il suo Create, inserendo una riga penso cosi' (giusto?:
   inherited Create(Anno,MM,ID,Conto,.....);
 
Ma se istanzio TMensiliB i valori Anno,mm,id, etc. come glieli do' ? Sono 
confuso ..
 

 Manca qualcosa per leggere un valore tra a01, a02 etc
 
Quello che l'OP ha postato è il tipico wrapper di un record, 
probabilmente nativo di altri tempi (intravedo antentati tipo file ad 
accesso random..)
 
Ad ogni modo, la regola classica è quella di aggiungere alla classe 
tutte le informazioni che essa può pubblicare, anche quelle ad accesso raro.
Tuttavia, se l'origine dei dati non contiene queste info ad accesso raro 
ma esse vengono lette in un secondo momento, allora l'OP può creare 
un'altra classe che contiene quelle info, ed aggiungerla alla classe 
principale.
In oop sarebbe una relazione di tipo "has a", cioè la classe principale 
ha un'istanza di una classe subdettaglio.
 
Se l'OP ci postasse la struttura stottostante dei dati, sarebbe più 
facile ricreare la classe che ne incapsula dati e logiche.
 
 
-- 
morde
Android
QT 4.7
Delphi (5,6,7.. expired)
Firebird Database
 

In effetti potrei, come consiglia Morde, aggiungere tutte le informazioni in 
un'unica classe. Ho inizialmente pensato di fare due classi per la diversa 
natura dei dati e vorrei continuare così per esercizio. Pertanto ho provato 
così. Ho definito una classe TBudget che contiene i dati fissi del budget:
Type
  TBudget  = class
    Anno   : string;
    id     : string;
    .............
    constructor create(aAnno, aId: string;.......); virtual;
end;
Il constructor e' imnplementato cosi':
constructor TBudget.Create(aAnno, aId: string;.......);
begin
   Anno:= aAnno
   Id:= aId;
   ............
end;
 
Ho definito un'altra classe derivata TMensiliB (che possiede dati numerici 
che possono cambiare mesilmente:
type
  TMensiliB = class(TBudget)
  private
    FMensiliB: TStringList;
  public
    property MensiliB: TStringList read FMensiliB;
    constructor Create(a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12: 
integer);
    function   GetMensiliB: TStringList;
end;
e ho implementato il constructor come segue:
constructor TMensiliB.Create;
begin
   inherited Create(Anno,Id,....);  // costruttore di TBudget
   FMensiliB:= TStringList.Create;
end;
 
e l'utilizzo è come segue:
var
   oMensili: TMensiliB;
..........
   Acces the BudgetTable ...
 
   oMensili:= TMensiliB.Create(
                          BudgetTable.FieldByName('Y01').AsInteger,
                          ............................................................... 
 );
 
   oMensili.Anno   := BudgetTable.FieldByName('ANNO').AsString;
   oMensili.Id        := BudgetTable.FieldByName('ID').AsString;
   .........................................................................................
                              ............................................................................
 
Lo intuisco già che non è un gran che, ma non riesco a far meglio. Quando 
istanzio TMensili, il Create crea correttamente gli importi mensili nella 
StringList MensiliB, ma gli altri dati della classe base non ci sono alla 
sua creazione e non ho trovato altro modo che fare delle assegnazioni... Ma 
come potrei fare ?
 
Per ciò che concerne la struttura sottostante dei dati, è esattamente 
corrispondente ad un record di una TTable (BudgetTable) da cui essi 
provengono inizialmente, ma potrebbero essere anche forniti da input diretto 
dell'utente...