Record, Object, Class. Warum nicht nur Object?

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von mse »

Warf hat geschrieben:Ja so ists mMn auch gut (Bis auf das ich echt kein Fan von eckigen klammern bin). Du hast generell viele gute Ideen zu MSELang, und die Sprache ist auch interessant, leider stellt es für mich (noch) keine alternative da.

Eckige Klammern werden unter anderem für "attachments" verwendet, welche in MSElang eine wichtige Rolle spielen.

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von Soner »

Warf hat geschrieben:..
Aber es geht mir vor allem auch um die Typnamen. Eine strikte Trennung der Namen von Klasse und Record mit entsprechender eigenständigen Syntax für beides, macht das lernen natürlich deutlich einfacher. Ich habe bereits ein paar mal objects verwendet, doch ich muss trozdem immer wieder nachschauen wie die Syntax ist, denn so was:

Code: Alles auswählen

Var
  Shape1, Shape2 : PShape;
  Rectangle : PRectangle;
  Square : PSquare;
 
begin
  Shape1 := new (PShape, Init(1, 1, 1, 1) );
  Shape2 := new (PShape, Init(2, 2, 2, 2) );
 
  new (Rectangle, Init(11, 22, 33, 44) );
 
  new(Square);
  Square^.Init(111, 222, 333, 444);
 
//...
dispose(Shape1);
  dispose(Shape2, CleanUp);
 
  Rectangle^.CleanUp;
  dispose(Rectangle);
 
  dispose(Square, CleanUp);

finde ich ist eine super verwirrende Syntax. Da ist das Typ.Create von Klassen doch deutlich intuitiver.

Mal ganz davon abgesehen, dass ich der meinung bin bei Stack objects sollte Konstruktor und Destrukor automatisch aufgerufen werden.


Wieso verwirrend?

Code: Alles auswählen

 
Var
  Shape1, Shape2 : PShape;
  Rectangle : PRectangle;
  Square : PSquare;
 
begin
  new (Shape1, Init );       // Init(1, 1, 1, 1)  muss man auch bei TClass machen: 
                                      //  Shape1 := TShape.Create(1,1,1,1);
                                      // bzw.
                                      //  Shape1:=new (PShape, Init );    vs. Shape1 := TShape.Create;
  dispose(Shape1, Done); // Als Class: Shape1.Free;
 
  //Ansonsten benutzung ist gleich
 
 

Mann könnte auf auch die Unterscheidung zwischen "TShape" und "PShape" aufheben, fall es möglich ist.

Warf hat geschrieben:..
Aber es geht mir vor allem auch um die Typnamen. Eine strikte Trennung der Namen von Klasse und Record mit entsprechender eigenständigen Syntax für beides, macht das lernen natürlich deutlich einfacher.
...


Das soll deutlich einfacher sein: :roll:

Code: Alles auswählen

 
type
 TFussball = record
   farbe: integer;
  end;
 
 TBasketball = class
   farbe: integer;
  end;
 
 TVolleyball = object
   farbe: integer;
  end;
 


Und das ist komplieziert ?

Code: Alles auswählen

 
type
 TFussball = object
   farbe: integer;
  end;
 
 TBasketball = object
   farbe: integer;
  end;
 
 TVolleyball = object
   farbe: integer;
  end;
 

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von Soner »

mse hat geschrieben:..

Code: Alles auswählen

 
var
  x,y: ^^integer;
 

Meinte ich.
..

Das kenne ich gar nicht mehr. Eigentlich habe ich nach dem umstieg auf Delphi Zeiger kaum noch verwendet, sehr selten und meistens nur bei dynamische Records und bei Bitmaps.


mse hat geschrieben:..
Mit Objekten scheinen mir constructor() und destructor() eher passend statt new() und dispose().

Jedem das Seine. Ich wünsche dir viel Erfolg mit Mselang.

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von Soner »

Bei der ganzen Betrachtung fehlen die Eigenschaftsobjekte:

Code: Alles auswählen

 
type
 TKindObject = object
 
  end;
 
  TMyObject = object
     kind1 : TKindObject; //wie soll man das jetzt erstellen, mit New im Konstruktor von  TMyObject--
  end;
 


Ich glaube Borland hatte damals in Delphi Klassen eingeführt um solche Probleme zu lösen. Damals waren viele Programmier unzufrieden mit object-orienrtierte Programmierung in Turbo Pascal.

Lange Rede kurze Sinn "Record + Class" gut, "Object" shit. :D
Zwei Sonntage mit Probleme die vor 22 Jahren gelöst sind verbraten. :D

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von mse »

Soner hat geschrieben:Bei der ganzen Betrachtung fehlen die Eigenschaftsobjekte:

Code: Alles auswählen

 
type
 TKindObject = object
 
  end;
 
  TMyObject = object
     kind1 : TKindObject; //wie soll man das jetzt erstellen, mit New im Konstruktor von  TMyObject--
  end;
 


??? Ich verstehe nicht wo das Problem liegt. In deinem Beispiel braucht TKindObjekt keinen Speicher.
Hier

Code: Alles auswählen

 
type
 TKindObject = object
  f1: integer;
  f2: integer;
  end;
 
  TMyObject = object
     kind1 : TKindObject; //wie soll man das jetzt erstellen, mit New im Konstruktor von  TMyObject--
  end;
 

werden für "kind1" 2*4 Bytes reserviert wie wenn TKindObject als "record" definiert wäre.

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von Soner »

Mit meinem Beispiel habe ich das Problem nur angedeutet. Stelle dir vor das Kindobjekt wäre so etwas wie TForm, das viele unterobjekte hat und die müssen automatisch erstellt werden, weil man sie nicht sieht. Man hat nur Einfluß auf das übergeordnete Object. Wie soll man diese untergeordnere Objekte definieren als PObject und mit New auf Heap oder als TObject und auf Stack. Ich glaube damals hat Borland aus diesem Grund Klassen erfunden.

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von kupferstecher »

Soner hat geschrieben:Vielleicht sollte man Zeigeroperator "^" aus Anweisungsblock komplett entfernen und nur bei Type- und Variablendefinition benutzen. Und wenn man dann in Anweisungsblock Zeigertypen verwendet, dann meint man immer den Wert nicht die Adresse:

Das gleiche hab ich mir auch schon mal gedacht. Ich glaube nämlich, dass die Schwierigkeiten mit Zeigern allein darauf beruhen, dass man ohne langjährige Gewöhnung mit Zeigern den Code nicht intuitiv runterlesen kann. Obwohl es ja nur zwei Operatoren gibt. Es sind aber immer Variablen mit im Spiel, und die funktionieren in einer versetzten Logik.
Mit Soners Vorschlag steckt in Pointern und Variablen die gleiche Syntaxlogik. Den Dereferenzierungsoperator braucht man aber trotzdem noch um kompakten Code zu schreiben, z.B.

Code: Alles auswählen

IntVar2:= ^(@IntVar1 + 10);      //Adressoffset von 10

wobei hier nichtmal Zeigervariablen verwendet wurden.

Class mit eigenständiger Syntax halte ich aber trotzdem für wichtig. Sonst muss man jede Variable mit Zeiger deklarieren, was doch hässlich ist.

@MSE, ich bin immernoch der Meinung, dass du 'Object' nicht als Schlüsselwort verwenden solltest, sondern 'Record'. Das pascalsche Object hat doch auf Rechnern mit dynamischer Speicherverwaltung kaum eine sinnvolle Anwendung und dein 'Object' wird in diesem Umfeld wohl meistens als einfaches 'Record' verwendet. Die Programmierer sind auch an den Begriff Record gewohnt. Die Bezeichnung nimmt ja nichts den Möglichkeiten weg.

@Soner, in deinem Beispiel werden die Objekte ja statisch angelegt, wenn sie nicht als Zeiger deklariert werden. Ein Object kann damit in sich keine Deklaration seiner selbst beinhalten, außer als Zeiger.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von mse »

Soner hat geschrieben:Mit meinem Beispiel habe ich das Problem nur angedeutet. Stelle dir vor das Kindobjekt wäre so etwas wie TForm, das viele unterobjekte hat und die müssen automatisch erstellt werden, weil man sie nicht sieht. Man hat nur Einfluß auf das übergeordnete Object. Wie soll man diese untergeordnere Objekte definieren als PObject und mit New auf Heap oder als TObject und auf Stack. Ich glaube damals hat Borland aus diesem Grund Klassen erfunden.

Man definiert sie je nach dem was geeigneter ist entweder inline im eigenen Speicherblock oder extern als Pointer. Das ist ja der Vorteil von Objekten, dass sie beides ermöglichen.
kupferstecher hat geschrieben:
Soner hat geschrieben:Vielleicht sollte man Zeigeroperator "^" aus Anweisungsblock komplett entfernen und nur bei Type- und Variablendefinition benutzen. Und wenn man dann in Anweisungsblock Zeigertypen verwendet, dann meint man immer den Wert nicht die Adresse:

Das gleiche hab ich mir auch schon mal gedacht. Ich glaube nämlich, dass die Schwierigkeiten mit Zeigern allein darauf beruhen, dass man ohne langjährige Gewöhnung mit Zeigern den Code nicht intuitiv runterlesen kann.

Bleibt das Problem der mehrfach-Pointer und der Pointer-Arithmetik.

Code: Alles auswählen

 
type
 pint32 = ^int32;
 ppint32 = ^pint32;
...
var
 pi1 = pint32;
 ppi1 = ppint32;
..
 //wie spricht man mit der neuen Syntax den int32 Wert an der hinter ppi1 steht?
 inc(i1); //was ist hier mit der neuen Syntax gemeint?
 

Für Pointer auf "record" und "object" gibt es in FPC wie von warf schon geschrieben{$ModeSwitch AUTODEREF+}, AFAIK default on im Delphi Modus.
@MSE, ich bin immernoch der Meinung, dass du 'Object' nicht als Schlüsselwort verwenden solltest, sondern 'Record'. Das pascalsche Object hat doch auf Rechnern mit dynamischer Speicherverwaltung kaum eine sinnvolle Anwendung und dein 'Object' wird in diesem Umfeld wohl meistens als einfaches 'Record' verwendet. Die Programmierer sind auch an den Begriff Record gewohnt. Die Bezeichnung nimmt ja nichts den Möglichkeiten weg.

Warum "record" wenn es Objekte sind? Möglicherweise wird es in MSElang zusätzlich auch "record" geben für anonyme Definitionen.

Code: Alles auswählen

 
type
 obj1ty = object
  f1: int32;
  f2: int32;
  f3: record
   a,b: flo64;
  end;
  method test(const a: int32);
 end;
 

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von kupferstecher »

mse hat geschrieben:Bleibt das Problem der mehrfach-Pointer und der Pointer-Arithmetik.

Das stimmt, das ist ein Problem. Mit gewohnter Dereferenzierung ließe sich auch das lösen, ist dann halt wieder nicht sehr schön. Aber wer einen Pointer auf einen Pointer braucht, den sollte das nicht abschrecken~

//wie spricht man mit der neuen Syntax den int32 Wert an der hinter ppi1 steht?


Code: Alles auswählen

 
type
 pint32 = ^int32;
 ppint32 = ^pint32;
var
 pi1 = pint32;
 ppi1 = ppint32;
 

Code: Alles auswählen

 
AInt:= pi1;        //klar, Wert von pi ist Typ Integer;
AInt:= ppi1^;      //Wert von ppi1 ist Pointer, um Integer zu erhalten ist 'traditionelles' Dereferenzieren notwendig.
 
inc(pi1);          //Zielwert (Integer) wird erhöht (Implizite Dereferenzierung)
inc(ppi1);         //Poniteradresse von pi1 wird erhöht, da implizite Dereferenzierung nur über eine Stufe
inc(ppi1^);        //gleich wie inc(pi1)
inc(@pi1);         //gleich wie inc(ppi1)
 



@MSE, ich bin immernoch der Meinung, dass du 'Object' nicht als Schlüsselwort verwenden solltest, sondern 'Record'.

Warum "record" wenn es Objekte sind?

Es sind ja auch Records, das ist ja das schöne an deiner Syntax. Also warum "Object" wenn es (auch) Records sind?
Der Begriff Record verdeutlicht den Character der statischen Speicherverwaltung. Wer Records/Structs aus anderen Sprachen kennt, für den ist klar, dass kein Konstruktor benötigt wird. Die Verwirrung bei Objekten kann man ja sogar hier im Thread lesen.
D.h. der Begiff Record würde die syntaktische Verwendung hervorheben, der Begriff Object dagegen die OOP-Fähigkeiten. Letztere muss m.E. für die Lernbarkeit der Sprache aber weniger deutlich herausgestellt werden.


Möglicherweise wird es in MSElang zusätzlich auch "record" geben für anonyme Definitionen.

Das finde ich auch wieder eher verwirrend. Warum nicht einfach Object? Bzw. Record, falls ich dich doch noch überzeugen kann :-)

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von kupferstecher »

Nachtrag: Da fällt mir ein, wie sieht es denn mit der Kompatibilität bei C-Aufrufen aus? Ich vermute, dass das auch ein Grund ist, warum in FreePascal an den ursprünglichen Records festgehalten wird?

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von mse »

Wenn ich richtig verstehe bedeutet in der neuen Syntax '^' die Dereferenzierung, wenn aber die Dereferenzierung nur über eine Stufe geht, schreibt man '^' nicht; '@' ist normalerweise der Adresseoperator, bei einer Pointer-Variable dagegen der direkte Zugriffsoperator. Das überzeugt mich nicht da inkonsequent.
Zum Unterschied zwischen "record" und "object": ein Record beinhaltet ausschliesslich Daten, ein Objekt kann zusätzlich Verhalten (= Methoden) haben.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von mschnell »

Nö. Neuerdings haben Records in Delphi (und fpc) auch Methoden, sind also eigentlich das, was bei TurboPascal "Object" hieß.

Für mich ist aber ein "Objekt" eine Instanz (einer Klasse) (oder ein Zeiger darauf) und kein Typ.

Deshalb finde ich die Idee sehr gut, den Typ von etwas, das nicht zwingend auf dem Heap liegen muss und Variablen und Methoden (und Properties als die Kombination aus beidem) hat, "Record" zu nennen. von mir aus auch "Class", aber möglichst nicht "Object".

-Michael

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von mse »

Na dann halt Objekttyp. Mit

Code: Alles auswählen

 
 type
  xx = object
 

stimmt's ja dann. ;-)

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von kupferstecher »

mse hat geschrieben:Wenn ich richtig verstehe bedeutet in der neuen Syntax '^' die Dereferenzierung, wenn aber die Dereferenzierung nur über eine Stufe geht, schreibt man '^' nicht;
[...]inkonsequent.

So formuliert hört sich das inkonsequent, ja inkonsistent, an. Nach meiner Denke wäre aber ein Pointer nicht mehr ein "Pointer auf einen Datentyp", sondern ein "Datentyp mit variabler Adresse" (und ohne reservierten Speicher). ^Integer also ein Integer mit veränderbarer Adresse. Der Zugriff erfolgt immer wie beim normalen Datentyp und auf die Adresse wird immer mit dem Adressoperator zugegriffen, sowohl lesend als auch schreibend. Bei Pointer auf Pointer eben ein Pointer mit variabler Adresse. Hier wirds unschön, das sehe ich auch so, ist aber eher ein seltener Fall.
Ich vermute, dass du Pointer eben schon so verinnerlicht hast, dass du das Problem der verschobenen Logik gar nicht mehr siehst, nämlich die, dass man auf den Wert eines Integer direkt zugreift, zum Zugriff auf den Wert eines Integer-Pointers jedoch manuell dereferenzieren muss. Die Variablenbezeichnung eines Integer bildet ja letztlich auch eine Adresse im Speicher ab, trotzdem muss man nicht händisch dereferenzieren. Klar, beim Pointer kommt insgesant eine zusätzliche Stufe der Dereferenzierung dazu...

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Record, Object, Class. Warum nicht nur Object?

Beitrag von mschnell »

mse hat geschrieben:Wenn ich richtig verstehe bedeutet in der neuen Syntax '^' die Dereferenzierung, wenn aber die Dereferenzierung nur über eine Stufe geht, schreibt man '^' nicht; '@' ist normalerweise der Adresseoperator, bei einer Pointer-Variable dagegen der direkte Zugriffsoperator. Das überzeugt mich nicht da inkonsequent.

Stimmt. Genau wie eine Prozedur-Variable, auf die in Delphi (immer schon) eine Prozedur zugewiesen wird, und nicht - wie es konsequent wäre - (und in fpc auch möglich) die Adresse einer Prozedur mit "@".
-Michael

Antworten