Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Class -->Error (https://www.delphipraxis.net/127234-class-error.html)

Teekeks 9. Jan 2009 16:03


Class -->Error
 
Hallo!
Ich probiere mich gerade an Klassen aus und bin auf ein von mir unlößbares Problem gestoßen.
Hier erstmal mein bisheriger Code:
Delphi-Quellcode:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 =class;

  TTier = class
  private
    pArt:string;
    pAlter:integer;
    pGeschlecht:string;
    pKrankheit:string;
  public
    constructor Create(Krankheit:string; Geschlecht:string; Art:string);
  published
    property getTierart:string read pArt;
    property getAlter:integer read pAlter;
    property getGechlecht: string read pGeschlecht;
    property getKrankheit:string read pKrankheit;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
    Tier:TTier;
  end;


var
  Form1: TForm1;

implementation

{ TForm1 }
constructor TTier.Create(Krankheit:string; Geschlecht:string; Art:string);
begin
  pAlter:=0;
  pGeschlecht:=Geschlecht;
  pArt:=Art;
  pKrankheit:=Krankheit;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Tier.Create('Gesund','Weiblich','Katze');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Label1.Caption:=Tier.pKrankheit;
  Label2.Caption:=Tier.pArt;
  Label3.Caption:=Tier.pGeschlecht;
  Label4.Caption:=inttostr(Tier.pAlter);
end;

initialization
  {$I unit1.lrs}

end.
jestz bekomme ich wenn ich auf Button1 Klicke eine meldung:
Zitat:

Zitat von Lazarus
Project project1 raised exception class 'External: SIGSEGV'

Was mache ich falsch? weil eigentlich (wenn ich die Fehlermeldung richtig Deute) will der mich ja darauf hinweisen das ich die Klasse nicht "created" habe,oder? :gruebel:

gruß Teekeks

Dax 9. Jan 2009 16:05

Re: Class -->Error
 
Zitat:

Zitat von Teekeks
weil eigentlich (wenn ich die Fehlermeldung richtig Deute) will der mich ja darauf hinweisen das ich die Klasse nicht "created" habe,oder? :gruebel:

Genau, es muss nämlich ":= TTier.Create" heissen, nicht ".Create".

NormanNG 9. Jan 2009 16:06

Re: Class -->Error
 
Hi,

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  Tier := tTier.Create('Gesund','Weiblich','Katze');
end;

Teekeks 9. Jan 2009 16:10

Re: Class -->Error
 
ah. Danke!

quendolineDD 9. Jan 2009 16:27

Re: Class -->Error
 
Genauso heißt es aber auch nicht
Delphi-Quellcode:
Label1.Caption:=Tier.pKrankheit;
sondern, da pKrankheit ein private-Attribut deiner Klasse ist, die du über deine property getKrankheit:string read pKrankheit; publishst (diese eingedeutschten Wörter :-\)
Delphi-Quellcode:
Label1.Caption := Tier.getKrankheit;

DeddyH 9. Jan 2009 16:40

Re: Class -->Error
 
Im Normalfall macht man das ja auch so:
Delphi-Quellcode:
  TTier = class
  private
    pArt:string;
    pAlter:integer;
    pGeschlecht:string;
    pKrankheit:string;
    function getTierart: string;
    function getAlter: integer;
    function getGechlecht: string;
    function getKrankheit: string;
  public
    constructor Create(Krankheit:string; Geschlecht:string; Art:string);
  published
    property Tierart:string read getTierart;
    property Alter:integer read getAlter;
    property Gechlecht: string read getGeschlecht;
    property Krankheit:string read getKrankheit;
  end;

...
function TTier.getTierart: string;
begin
  Result := pArt;
end;

//usw. für die anderen Properties
Wobei man statt pArt dann FArt etc. schreiben würde.

Teekeks 9. Jan 2009 16:53

Re: Class -->Error
 
Zitat:

Zitat von quendolineDD
Genauso heißt es aber auch nicht
Delphi-Quellcode:
Label1.Caption:=Tier.pKrankheit;
sondern, da pKrankheit ein private-Attribut deiner Klasse ist, die du über deine property getKrankheit:string read pKrankheit; publishst (diese eingedeutschten Wörter :-\)
Delphi-Quellcode:
Label1.Caption := Tier.getKrankheit;

das habe ich mitlerweile selber schon herrausbekommen. Ich konnte aber komischerweise Trozdem darauf zugreifen... warum eigentlich? :gruebel:

@deddyH:
Ich hab das jetzt so gelößt:
Delphi-Quellcode:
  TTier = class
  private
    procedure sAlter(NeuesAlter:integer);
  protected
    pArt:string;
    pAlter:integer;
    pGeschlecht:string;
    pKrankheit:string;
  public
    constructor Create(Krankheit:string; Geschlecht:string; Art:string);
    destructor Destroy;
  published
    property getTierart:string     read pArt;
    property getAlter:integer      read pAlter;
    property getGeschlecht: string read pGeschlecht;
    property getKrankheit:string   read pKrankheit;

    property setAlter:integer      write sAlter;
    property setKrankheit: string  write pKrankheit;
    property setGeschlecht: string write pGeschlecht;
    property setTierart: string    write pArt;
  end;
geht das so oder verstößt das total gegen die Programmierer-Ehtik? :-D

gruß Teekeks

quendolineDD 9. Jan 2009 16:56

Re: Class -->Error
 
Getter und Setter sind in der Regel Funktionen und Prozeduren, auf die über Properties zugegriffen wird und in denen die Verarbeitung der Attribute gezielt geregelt wird.

Uwe Raabe 9. Jan 2009 16:56

Re: Class -->Error
 
Zitat:

Zitat von Teekeks
Ich konnte aber komischerweise Trozdem darauf zugreifen... warum eigentlich? :gruebel:

Innerhalb der Unit, in der die Klasse deklariert ist, hat private keine Wirkung.

DeddyH 9. Jan 2009 16:56

Re: Class -->Error
 
Das ist so nicht im Sinne der OOP. Du hast eine Property (z.B. Name), welche über einen sog. Getter (z.B. GetName) ausgelesen und einen sog. Setter (z.B. SetName) gesetzt wird. Den Getter kannst Du meist auch weglassen und gleich den Feldinhalt zurückgeben, aber ein Setter kann zur Überprüfung ganz nützlich sein.

mkinzler 9. Jan 2009 16:56

Re: Class -->Error
 
Du verwechselst Properties mit Getter/Setter
Delphi-Quellcode:
published
    property Tierart:string     read pArt write pArt;
...

Teekeks 9. Jan 2009 17:26

Re: Class -->Error
 
Zitat:

Zitat von mkinzler
Du verwechselst Properties mit Getter/Setter
Delphi-Quellcode:
published
    property Tierart:string     read pArt write pArt;
...

aber, tut das nicht das selbe wie meins?

DeddyH 9. Jan 2009 17:29

Re: Class -->Error
 
Das ist der Direktzugriff auf ein privates Feld ohne explizite Getter/Setter.

Der_Unwissende 9. Jan 2009 17:29

Re: Class -->Error
 
Zitat:

Zitat von DeddyH
Das ist so nicht im Sinne der OOP. Du hast eine Property (z.B. Name), welche über einen sog. Getter (z.B. GetName) ausgelesen und einen sog. Setter (z.B. SetName) gesetzt wird. Den Getter kannst Du meist auch weglassen und gleich den Feldinhalt zurückgeben, aber ein Setter kann zur Überprüfung ganz nützlich sein.

Natürlich können auch Getter mal ganz sinnvoll sein ;-) So können Getter dyn. einen Wert berechnen und zurückgeben, statt dass man diesen immer in einer Variable speichert und aktuell hält. Als Beispiel könntest Du hier eine Liste von Zahlen implementieren, welche eine Methode zum hinzufügen von Werten besitzt. Eine mögliche Eigenschaft wäre dann der Mittelwert der eingefügten Zahlen. Den kannst Du halt nach jedem Einfügen berechnen und in einer Variable speichern oder Du verwendest einen Getter.

Delphi-Quellcode:
TMyList = class(TObject)
  private
    values: TIntegerDynArray;
  protected
    function getMean(): Integer;
  public
    procedure addValue(const value: Integer);
  published
    property mean: Integer read getMean;
end;
Für den Nutzer ist von "außen" nur das Property mean sichtbar, ob dies nun auf eine Variable zurückgreift oder wie hier eine Methode bemüht bleibt völlig transparent. Damit siehst Du schon eine wichtige Eigenschaft der Properties, Du kannst einfach leicht umstellen. Wird z.B. häufig auf den Mittelwert zugegriffen und nur sehr sehr selten (im Verhältnis dazu) ein neuer Wert eingefügt, dann wäre es wohl effizienter den Wert vorzuberechnen und in einer Variable zu speichern. Umgekehrt würde häufiges Hinzufügen von Werten und seltenes Lesen des Mittelwerts von der dyn. Berechnung profitieren. Somit kannst Du hier die Implementierung transparent austauschen. Für den Nutzer der Klasse gibt es immer nur ein Property, wo der zurückgelieferte Wert herkommt ist ihm egal.

Eine weitere wichtige Eigenschaft siehst Du auch noch, es gibt keine Möglichkeit von außen den Wert zu setzen. Das macht bei einem Mittelwert auch keinen Sinn, immerhin ist der ziemlich klar definiert und hängt allein von den Werten in der Liste ab. Da das Property mean hier nur eine read Eigenschaft besitzt verhält sich das Property wie eine Variable, die man eben nur lesen kann.

Natürlich gibt es auch Properties, die man sowohl Lesen als auch Setzen können muss, da hattest Du ja schon Beispiele gesehen. Die Vorteile sind natürlich die Gleichen. Insbesondere kann man (wie DeddyH ja sagte) eben auch die Gültigkeit prüfen. Z.B. könntest Du sicherstellen, dass das Alter >= 0 Jahre ist (ein Integer kann auch kleiner werden).

DeddyH 9. Jan 2009 17:35

Re: Class -->Error
 
Ich hatte ja auch nicht behauptet, dass Getter generell sinnlos sind ;). Nochmal ein Beispiel:
Delphi-Quellcode:
type
  TMyClass = class
  private
    FAge: integer;
    procedure SetAge(const value: integer);
    function GetAge: integer;
  public
    property Age: integer read GetAge write SetAge;
  end;

...

procedure TMyClass.SetAge(const value: integer);
begin
  if value > 0 then
    FAge := value
  else
    raise Exception.Create('Ungeborene gelten nicht.');
end;

function TMyClass.GetAge: integer;
begin
  Result := FAge; //einfacher Fall, könnte auch z.B. das Ergebnis einer Berechnung sein
end;

Teekeks 9. Jan 2009 17:39

Re: Class -->Error
 
hmm. ihr habt mich überzeugt.
Bringen wir das mal ein. ^^

Fussball-Robby 9. Jan 2009 18:05

Re: Class -->Error
 
Anhängig von deiner Delphiversion(in D7 gehts, in D5 noch nicht) kann Delphi dir auch helfen: Du erstellst zunächst die Klasse mir propertys:
Delphi-Quellcode:
type
  TMyClass = class
  private
    //
  published
    property Anzahl: Integer;
  end;
Und drückst dann Strg + Shift + C. Das private Feld mit dem führenden 'F' und die Setter-Methode werden dann automatisch erstellt.

Teekeks 10. Jan 2009 06:06

Re: Class -->Error
 
hmmm. Ich verwende Lazarus. aber die haben da auch irgentsowas in der art... Ich guck mal.
Danke!


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:08 Uhr.

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