Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Unit Aufbau (https://www.delphipraxis.net/65843-unit-aufbau.html)

Ruffy87 21. Mär 2006 12:01


Unit Aufbau
 
Hallo,

zuerst mal ein kleiner Screenshot vom CodeExplorer:

http://people.freenet.de/www.ruffy.de/DelphiUnit.jpg

Jetzt meine Frage dazu:
Was ist der Unterschied wenn ich eine procedure in den Teil von "TFormHaupt->Public/Private"
oder direkt in den "Ordner Proceduren" schreibe?

So wie ich das in der Schule verstanden habe:
Der Public Teil ist dafür da, damit man von anderen Units auf die Methoden
im Public Teil drauf zugreifen kann. Dann gibt es noch einen Private Teil
der nur für die Methoden intern in der Unit ist.

Wofür ist dann der Eintrag "Prozeduren" auf der Ebene von "TFormHaupt" da?

Mit freundlichen Grüßen

Stefan

ichbins 21. Mär 2006 12:33

Re: Unit Aufbau
 
wenn du sie in den private-Bereich des Forms schreibst, dann gehört die Prozedur/Funktion der Form, also der Klasse. Diese nennt sich dann METHODE. Um sie aufzurufen, brauchst du eine Variable vom Typ der Klasse (also TFormhaupt), deren Funktion du dann aufrufst, also so:
Delphi-Quellcode:
unit1.formhaupt1.methode;
Von dieser Methode aus kannst du dierekt Untereigenschaften oder andere Methoden der Form zugreifen, also einfach so:
Delphi-Quellcode:
methode2;
//oder
button1.caption:='';
Wenn du die Prozedur in die Unit schreibst, ist sie dierekt von der Unit abhängig und nicht von einer Klasse:
Delphi-Quellcode:
unit1.prozedur;
alle Prozeduren wie buttonclick oder so sind Methoden der Form.


Wenn du auf Komponenten oder Eigenschaften der Form zugreifen willst, dann verwende Methoden, wenn du unabhängige Funktionen schreiben willst, Funktionen und Prozeduren dierekt in der Unit.



Die Unterbereiche Public und Private beschreiben, wie du schon gesagt hast, die Zugriffsrechte auf die Methoden und Eigenschaften der Klasse. Wenn du sie in private schreibst, kann man nur von anderen Methoden der Klasse aus darauf zugreifen, wenn du sie in public schreibst, kann man auch von Methoden anderer Klassen oder Prozeduren/Funktionen die dierekt zur Unit gehören zugreifen.

Ruffy87 21. Mär 2006 14:34

Re: Unit Aufbau
 
Also zuerst mal danke für deine Antwort.

Hab die Sachen selbst noch mal testet.

1. Erkenntnis

Für den Aufruf muss man nicht noch den Unit Namen vorranstellen, sondern kann
einfach so schreiben(z.B. in einem OnClick-Ereignis der Form ist):

Code:
methode
2. Erkenntnis

Wenn ich eine Prozedur in eine Unit1 schreibe und diese von einer Unit2 aufrufen möchten
dann klappt dein angegebener Code "Unit1.prozedur" nicht.(natürlich hab ich die Unit1 in
uses von Unit2 eingebunden)
Ich glaube, das wenn ich eine Prozedur direkt in die Unit schreibe diese auch nur
in der jeweiligen Unit verwenden werden kann.

Grishnak 21. Mär 2006 14:47

Re: Unit Aufbau
 
Zitat:

Zitat von Ruffy87
2. Erkenntnis

Wenn ich eine Prozedur in eine Unit1 schreibe und diese von einer Unit2 aufrufen möchten
dann klappt dein angegebener Code "Unit1.prozedur" nicht.(natürlich hab ich die Unit1 in
uses von Unit2 eingebunden)
Ich glaube, das wenn ich eine Prozedur direkt in die Unit schreibe diese auch nur
in der jeweiligen Unit verwenden werden kann.

Damit du von außerhalb der Unit auf Funktionen/Prozeduren zugreifen kannst, musst du diese im "Interface"-Teil der Unit bekannt machen:

Delphi-Quellcode:
unit Test;

interface

procedure Sichtbar(a: string);

implementation

procedure Sichtbar(a: string); // kann von jeder Unit, die diese Unit per Uses einbindet aufgerufen werden
begin
  [...]
end;

procedure Unsichtbar(x: single); // kann nur innerhalb dieser Unit aufgerufen werden
begin
  [...]
end;
end.

Der_Unwissende 21. Mär 2006 15:02

Re: Unit Aufbau
 
Hi,
gute Erkenntnis! Aber da gibt es noch ein wenig zu ergänzen.

Das man die Unit-namen nicht voran stellen muss, ist zwar soweit richtig. Trotzdem gibt es auch die Möglichkeit dies zu tun, bleibt die Frage warum?! Zu der Erkenntnis kommst du ganz leicht, wenn du mal zwei gleich benannte Funktionen/Prozeduren/Klassen/Konstanten/.... hast. Sagen wir der Einfachheit halber, du hast 2 Units, die eine Konstante CFILE_NAME besitzen. Seien nun beide Units in der Unit Unit3 eingebunden. Jetzt möchtest du gucken ob die beiden CFILE_NAME Werte gleich sind. Problem gibst du CFILE_NAME ein, hast du einen Wert, doch welchen? In Delphi wird das durch die Reihenfolge in der uses bestimmt (letztere sind immer "wichtiger"). Also ist es einfach sauberer / sicherer den Unitnamen voran zu stellen.

Eine andere Sache ist dass man Methoden nur in der gleichen Unit benutzen darf. Es würde natürlich wenig Sinn machen, zumal du schon einen Haufen Units in deinem Form automatisch eingebunden hast. Könntest du hiervon keine Methode benutzen, nun ja...
Es gibt einen Mechanismus, der ein wenig den Sichtbarkeiten von Klassen entspricht. Wie du in deinen Formularen siehst, gibt es zwei Abschnitte in einer Unit, Interface und Implementation.
Der Interface Teil dient der veröffentlichung von Schnittstellen (Interface). Hier wird alles das eingetragen, was nach aussen (ausserhalb der Unit) auch sichtbar ist. Natürlich sind Typdeklarationen und Konstanten auch in der gesamten Unit sichtbar.
Der Implementation Teil dient der Implementierung. Hier kommt also der Code rein. Jede nicht abstrakte, nicht geforwardete und nicht externe Prozedur/Funktion muss im Implementationteil implementiert werden.
Diese Methoden müssen implementiert werden, aber du kannst auch weitere anlegen. Diese sind dann nicht von aussen zugänglich (das Phänomen, auf dass du gestossen bist). Sie werden einfach als Hilfsmethoden für die anderen benutzt.

Gruß Der Unwissende

Ruffy87 21. Mär 2006 15:29

Re: Unit Aufbau
 
Danke an alle
:-D

Ruffy87 21. Mär 2006 16:13

Re: Unit Aufbau
 
Hab noch eine letzte Frage(das ist eigentlich meine Hauptfrage bei dem Thema):

Eine Methode im Public Teil muss man schreiben, wenn man diese von anderen Units aufrufen will,
das ist jetzt klar.

Wenn ich aber jetzt eine Prozedur schreiben will, die nur in der einen Unit/Form verwendet werden soll,
könnte ich die Prozedur ja entweder in den Private Teil schreiben oder direkt in die Unit.
Wann mache ich den was?

Ein Bsp. von meinem Programmcode:
1. Möglichkeit

Delphi-Quellcode:
procedure BK_Suchen(BK_Name:String; var BK: TTreeNode);
var TV_Count, BK_Index:integer;
    BK_Gefunden: Boolean;
begin
  with FormHaupt do
  begin
//Variablen initialisieren
    BK_Gefunden := false;
    TV_Count := TreeViewHaupt.Items.Count - 1;
    BK_Index := -1;

//Eintrag suchen
    repeat
      inc(BK_Index);
      BK := TreeViewHaupt.Items[BK_Index];
      if BK.Text = BK_Name then
        BK_Gefunden := true;
    until(BK_Gefunden) or (BK_Index = TV_Count);
  end;
end;
2. Möglichkeit

Delphi-Quellcode:
interface
...
  private
    procedure BK_Suchen(BK_Name:String; var BK: TTreeNode);
...
implementation
...
procedure TFormHaupt.BK_Suchen(BK_Name:String; var BK: TTreeNode);
var TV_Count, BK_Index:integer;
    BK_Gefunden: Boolean;
begin
//Variablen initialisieren
  BK_Gefunden := false;
  TV_Count := TreeViewHaupt.Items.Count - 1;
  BK_Index := -1;

//Eintrag suchen
  repeat
    inc(BK_Index);
    BK := TreeViewHaupt.Items[BK_Index];
    if BK.Text = BK_Name then
      BK_Gefunden := true;
  until(BK_Gefunden) or (BK_Index = TV_Count);
end;
...
Beides funktioniert, aber wann wende ich was an?

xaromz 21. Mär 2006 16:35

Re: Unit Aufbau
 
Hallo,

Deine erste Lösung funktioniert nicht, da Du auf Eigenschaften/Objekte Deines Forms zugreifst (TreeViewHaupt). Du musst also immer
Delphi-Quellcode:
FormHaupt.TreeViewHaupt
schreiben.
Was machst Du aber, wenn Du Dein Form mehrfach verwendest und das Objekt dann nicht FormHaupt heisst?

Wenn Du also auf Eigenschaften einer Klasse zugreifst (ein Formular ist ja auch eine Klasse), benutze immer die untere Lösung.

Gruß
xaromz

Ruffy87 21. Mär 2006 16:45

Re: Unit Aufbau
 
Beide Lösungen funktionieren bei mir zu 100%.

Und es ist doch egal ob man schreibt:

Delphi-Quellcode:
with FormHaupt do
begin
  TreeViewHaupt.Eigenschaft;
end;
oder

Delphi-Quellcode:
FormHaupt.TreeViewHaupt.Eigenschaft;

xaromz 21. Mär 2006 16:56

Re: Unit Aufbau
 
Hallo,

da hatte ich das
Delphi-Quellcode:
with FormHaupt do
übersehen.

Der Rest meines Postings ist trotzdem gültig.

Gruß
xaromz

Ruffy87 21. Mär 2006 17:38

Re: Unit Aufbau
 
Weiß einer auch was Published bedeutet(also vom CodeExplorer, siehe oberes Bild)?
oder welche Unterschiede es zwischen Public und Published gibt?

Denn vom Englischen her bedeuten Sie fast das selbe.

ichbins 21. Mär 2006 17:45

Re: Unit Aufbau
 
In der Hilfe steht da eine ellenlanger Artikel dazu...



achja, NIEMALS die Prozedur einfach so in die Unit schreiben sondern IMMER auch im Interface-Bereich reinschreiben. Sonst kann die Prozedur von anderen Prozeduren, die über der einen stehen, nicht aufgerufen werden etc.

Hansa 21. Mär 2006 18:04

Re: Unit Aufbau
 
Zusammenfassung :

1. private : gültig nur innerhalb der Klasse und nur von dieser zu "sehen" bzw. zu manipulieren. Nix drin mit
Delphi-Quellcode:
Form1.i := 0;
sofern i als private in Form2 deklariert wurde.

2. protected : hier vorerst keine Erklärung. Sehr wichtig bei größeren Programmen, die OOP auch nutzen.

3. public : von überall her zugreifbar auch außerhalb der Unit, wo das definiert wurde. Also :
Delphi-Quellcode:
Form2.i := Form2.j;
geht damit sehr wohl.

4. published : ähnlich wie public, allerdings hauptsächlich für OI gedacht und wichtig bei Entwicklung eigener Komponenten.

Aber all das ist nur die Spitze des Eisbergs, denn jetzt kommt noch vor allem virtual und override ins Spiel. Unerläßlich in Zusammenhang mit 2. protected. Das ganze ist nicht ganz so trivial, wie es vielleicht aussieht !

Der_Unwissende 21. Mär 2006 18:10

Re: Unit Aufbau
 
Zitat:

Zitat von ichbins
achja, NIEMALS die Prozedur einfach so in die Unit schreiben sondern IMMER auch im Interface-Bereich reinschreiben. Sonst kann die Prozedur von anderen Prozeduren, die über der einen stehen, nicht aufgerufen werden etc.

Sorry, aber das stimmt so auch nicht. Wie bereits erwähnt kannst du Prozeduren auch nur im Implementationteil benutzen, wenn es Prozeduren sind, die eben nie von aussen aufgerufen werden sollen. Sagen wir mal (ganz stupide) du baust einen Rechner (wie kreativ). Deine Idee wäre es jetzt, dass deine Unit eine Methode Compute hat, die bekommt 3 Strings (eingegebene Zahlen + Rechenzeichen). Compute gibt dir den String zurück, der das Ergebnis repräsentiert.
Jetzt überlegst du dir, du möchtest als erstes mal die Strings auf Gültigkeit prüfen (deshalb sind's hier auch erstmal Strings). Dazu möchtest du entscheiden ob die Zahlen gültig sind und du das Rechenzeichen kennst. Nehmen wir nun an, du entscheidest dich das in Methoden auszulagern, dann könnte es zu folgendem kommen:

Delphi-Quellcode:
interface
  function compute(const Number1, Number2, Operator : String) : String;

implementation
 
  // forwarded, da die Implementierung nach dem ersten Aufruf folgt
  function isValidNumber(const Number : String) : Boolean; forward;
  function isValidOperator(const Operator : String) : Boolean; forward;

  function compute(const Number1, Number2, Operator : String) : String;
    begin
      // testen ob gültige Nummern und Operator
      if isValidNumber(Number1) and isValidNumber(Number2) and isValidOperator(Operator) then
        begin
          ...
        end; // if isValidNumber(Number1) and isValidNumber(Number2) and isValidOperator(Operator)
    end; // function compute(const Number1, Number2, Operator : String) : String;

  function isValidNumber(const Number : String) : Boolean;
    begin
      ...
    end;
Wichtig ist halt nur, dass Methoden die folgen mit forward deklariert oder halt vor dem ersten Aufruf implementiert werden müssen. Es macht aber durchaus Sinn Methoden nur im Implementationteil zu halten.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:28 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz