Vererbung von Strukturen, Überladen von Prozeduren?

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Vererbung von Strukturen, Überladen von Prozeduren?

Beitrag von Xaby »

Ja, ich hab auch gemerkt, wenn ich die Sprite2D-Nummer als Sprite3D-Nummer benutze, dann ist bei mir nach 3 Sprites Schluss.

Schätze mal, der Speicher ist dann voll :?

Werde ich wohl nicht drum herum kommen, doch zwei IDs zu verwenden.

Ich dachte auch an eine "Zwischentabelle" die ich mir selbst anlege.

Zum Beispiel:

Sprite3DID
Sprite2DID
Sprite2D-Dateiname
Sprite2D-Transparenz

Denn aus dem gleichen Bild wird man eher sehr selten verschiedene Sprites mit unterschiedlichen Transparenzen erzeugen. Denn die hängen ja vom Bildinhalt ab.

Ich müsste dann in mehreren LinkedLists meine Objekte zusammenbasteln und das kann dann wieder langsam sein.

Also wenn mein Objekt weitere Informationen beinhalten soll,
müsste ich die Grunddaten aus meiner Liste zum Beispiel mit der Sprite3DID zusammen suchen.

Und das für jedes meiner Objekte. So suche ich dann ständig in zwei verschiedenen Listen.

Hierbei stellt sich mir auch die Frage, ob es eine einfachere schnellere Möglichkeit gibt, Eigenschaften zu vererben.

Was ist, wenn ich einfache 2D-Objekte haben möchte, und diese von mir aus nur Position und Ausdehnung haben. Und weitere 2D-Objekte, die spezieller sind ... aber die ersten Strukturwerte ebenfalls beinhalten sollen.

>>>>>>>>>>>>

Kann ich eine LinkedList mit mehreren Sturkturen machen?
Und in der LinkedList überprüfen, welche Struktur mein Objekt hat?

Als Beipiel:

Code: Alles auswählen

Structure Struk1
  x.l
  y.l
EndStructure

Structure Struk2
  x.l
  y.l
  Name.s
  Typ.l
EndStructure

NewList AlleOBJs.Struk*()

ForEach AlleOBJs()
  AlleOBJs()\x
  AlleOBJs()\y
  If AlleOBJs()\Name ; irgendwas mit Offset ... vielleicht

  EndIf
Next

Mein Problem ist auch, dass ich unter Umständen mein Objekt noch nicht richtig kenne. Und ihm vielleicht später weitere Eigenschaften zuweisen möchte.

Da wären wir wieder beim Thema LinkedLists in LinkedLists.

Könnte ja ein paar Strings in mein Objekt packen und diese beinhalten dann weitere Informationen über mein Objekt.

>>>>>>>>>>

Eine Möglichkeit wäre auch, dass man zwei LinkedLists nach einander für jede Struktur eine durchläuft. Und solle ein Objekt erweitert werden, fügt man ein neues der zweiten Struktur zu und löscht es aus der ersten.

Das macht die Sache aber auch etwas kompliziert, wenn ich mehrere verschiedene Objekttypen habe und diese zum Beispiel immer x,y besitzen und wenn ich eine Methode auf mein Objekt anwenden möchte, muss meine Prozedur ja immer neu geschrieben werden, weil die Struktur jedes mal neu ist.

Kann ich in PureBasic Methoden überladen?

In TurboPascal war das seltsam, man selbst konnte solche Befehle nicht basteln, aber zum Beispiel der Wirte()-Befehl konnte folgendes:

Write(0,"Hallo") hat in eine Datei mit Nummer "0" - "Hallo" geschrieben
Write(0) hat "0" auf dem Bildschirm ausgegeben
Wirte("Hallo") hat "Hallo" auf dem Bildschirm ausgegeben

Genauso möchte ich manchmal auch

ErstelleBild("Bildname von Festplatte")
ErstelleBild(30,30)

Das mit den Flags ist schon ne gute Idee, dass ich ""-Strings benutzen muss, um eine Eingabe zu umgehen ... das ist öde.

Und für jede neue Möglichkeit, die es geben kann, einen neuen Prozedurnamen zu erfinden, obwohl die Prozedur intern ja vollkommen gleich ist, wäre auch bescheuert.

:?

Link zu den LinkedLists in LinkedLists
http://www.purebasic.fr/german/viewtopi ... inkedlists

Ich nehme weiterhin meine Strings für dieses Problem :D
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

ist die lösung deines Problems vielleich das hier :

Code: Alles auswählen

Structure Struktur
  x.l 
  y.l 
EndStructure

Structure StrukturSpeziell Extends Struktur
  Name.s 
  Typ.l 
EndStructure

NewList AlleOBJs.StrukturSpeziell() 
StrukturSpeziell hätte dann am Anfang Struktur und dann das eigene.
Dann kannst du die "normalen" Sachen immer mit Struktur druch die gegend schicken, (also die ersten 8Byte), und wenn du halt alles braucht mit der StrukturSpeziell

und zu den gleichen Procedurenamen aber anderen Parameter:

Kannst du da nicht Macro nutzen, bei denen ist ja der Parameter typ "egal" du musst dann nur noch im Macro auf die richtige Procedure verweisen ...
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

@Stargate

Extends ist schon mal ein guter Hinweis

aber dass mir Macros in meinem Fall weiterhelfen, glaub ich noch nicht so recht.

Vielleicht kann man sich ne Brücke bauen.
Dass man das normale Objekt vor einem Prozeduraufruf in ein erweitertes umwandelt und nach dem Prozeduraufruf wieder zurück, um Speicher zu sparen. (wenn das so viel aus machen sollte)

Komplizierter wird es bei Strukturen, die zwar im Stamm gleich sind, aber in ihrer Erweiterung verschieden.

Nehmen wir dein Beispiel.

a.Struktur und b.Sturktur

Wie sieht jetzt die Prozedur aus, die a und b um 3 im X-Wert verändern kann?

Code: Alles auswählen

Structure Struktur
  x.l
  y.l
EndStructure

Structure StrukturSpeziell Extends Struktur
  Name.s
  Typ.l
EndStructure

Procedure SetzeX(c.Struktur)
  c\x+3
EndProcedure

Global a.Struktur
Global b.StrukturSpeziell

SetzeX(a)
SetzeX(b)

Debug a
Debug b

Wieso da ein Syntax-Error in der Prozedur SetzeX() ist, ist mir ein Rätsel.

:roll:
Kinder an die Macht http://scratch.mit.edu/
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

weil du keine strukturen byVal als argumente übergeben kannst.

das was du vorhast würde sowieso nicht funktionieren,
weil du danach so agierst, als wolltest du byRef übergeben.

...und ganz verkehrt ist dann der versuch, die proc, die auf eine struct ausgerichtet ist, mit einer anderen aufrufen zu wollen.

und was auch nicht klappt, eine struktur in ein Debug zu packen...

...

[edith]

so funktionierts das mit byRef:

Code: Alles auswählen

Structure Struktur
  x.l
  y.l
EndStructure

Structure StrukturSpeziell Extends Struktur
  Name.s
  Typ.l
EndStructure

Procedure SetzeX( *c.Struktur )
  *c\x+3
EndProcedure

Global a.Struktur
Global b.StrukturSpeziell

SetzeX(@a)
SetzeX(@b)

Debug a\x
Debug b\x
aber vorsicht:
das funktioniert bei Extend-Structs natürlich nur mit den feldern,
die im typ in der kopfzeile auch vorkommen.
wenn du also in einer struct auf das Feld "Name" zugreifen willst,
musst du einen Pointer auf eine Struct vom Typ "StrukturSpeziell" übergeben.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

@Kaeru Gaman
Sieht super aus, damit könnte man auf jeden Fall Objekte bearbeiten, die wenigstens einige gemeinsame Variablen in der Struktur haben.

Kaeru Gaman hat geschrieben:und was auch nicht klappt, eine struktur in ein Debug zu packen...
Zu meiner Verteidigung, war schon spät bzw. früh als ich das geschrieben hatte

Dank dir :allright:

Eins ist mir aber noch unklar. Wieso kann ich eine LinkedLlist einfach so übergeben, ohne Sternchen* und was bedeutet es, wenn ich in Klammern eine 10 schreibe also


Procedure SetzeX( c.Struktur(10))
...


Jetzt bleibt noch die Frage, ob ich für jeden spezielleren Objekttyp eine eigene Liste benötige. Aber das wird sich wohl nicht vermeiden lassen.

Code: Alles auswählen

Structure Struktur
  x.l
  y.l
EndStructure

Structure StrukturSpeziell Extends Struktur
  Name.s
  Typ.l
EndStructure

Procedure SetzeX( c.Struktur())
  c()\x+3
EndProcedure

NewList a.Struktur()
NewList b.StrukturSpeziell()

SetzeX(a())
SetzeX(b()) ; LinkedList doesn't match with the procedure parameter

Debug a()\x
Debug b()\x
Dank dir erstmal. Ich werde mir das mal anschauen :allright:
Kinder an die Macht http://scratch.mit.edu/
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

es ist schon so viel über OOP in PB geschrieben worden,
und jede menge anleitungen und includes, besonders in der Lounge,
also bevor du jetzt von deinem Level aus versuchst das ganze OORad
nochmal zu erfinden, setz dich doch lieber mit dem auseinander was es schon gibt,
da kommst du vielleicht schneller zum erfolg.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

Ich weiß, es gibt Units die OOP irgendwie in PureBasic realisieren. Aber das ist nicht das, was ich will :D
Den hier kenn ich ja
http://www.purebasic.fr/german/viewtopi ... hlight=oop
( Aber das Wort Preprozessor hat mir Angst gemacht und es scheint auch nicht auf MacOS zu laufen )

Mal ne andere Frage, vielleicht wird die ja in einem der vielen OOP-Versuchen beschrieben. Aber bin nicht drauf gestoßen.

Meine Prozedur:

Code: Alles auswählen

Procedure MaleKreis(x,y,Radius, Farbe)
So würde ich jede Variable angeben müssen

Code: Alles auswählen

Procedure MaleKreis(x,y,Radius=30, Farbe=#PB_Any)
So würde ich jede auf Radius und Farbe verzichten können.
Und wenn ich Farbe auf den Wert #PB_Any überprüfe, kann ich
eine Globale-Farbe nutzen.

Nun meine Frage, könnte ich auch folgendes realisieren:

Aufruf

Code: Alles auswählen

MaleKreis(x,y,40)
Nun soll aber Farbe nicht #PB_Any sein,
sondern auf den Radius reagieren.

Gibt es eine Möglichkeit, zu schauen, ob eine Funktion mit einem Parameter aufgerufen wurde?

Also ob Farbe beim Aufruf von MaleKreis angegeben wurde oder ob Farbe nicht angegeben wurde, sondern der Standard-Wert von Farbe benutzt wurde, der vorgegeben war.

>>>>>>>>>>>>>

Wenn ich nach Farbe teste, und Farbe nicht angegeben ist,
würde Farbe ja #PB_Any sein.

Wenn ich nach dem Radius teste, kann es sein, dass
ich ja die Farbe verändert hatte und damit meine Prozedur doch wieder mit der Farbe zusammen reagieren muss.

Eine dritte Möglichkeit wäre sicherlich, auf Radius und Farbe zu achten.
Also wenn Radius 40 und Farbe=#PB_Any, dann ...

Das Beispiel mit dem Kreis hinkt allerdings.

>>>>>

Die Sache würde bei mehr Parametern interessant sein.
Dann bräuchte man nur schauen, ob ein spezieller Parameter vom User angegeben wurde oder von der Prozedur selbst vorgeschlagen wurde als alle Kombinationen im Zusammenhang zu testen.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Vielleicht bei einem Bild.

Code: Alles auswählen

LadeBild(Name$,100,100)

LadeBild(Name$)

LadeBild()

Bei dem ersten Aufruf soll ein Bild mit dem Namen Name$ geladen werden und das Bild soll 100 x 100 sein. Wenn das Bild nicht vorhanden ist, wird eine leere Fläche angelegt die 100 x 100 ist. Das ist noch einfach.

Beim zweiten Aufruf soll standardmäßig ein Bild geladen werden und die Ausmaße sollen dem Bild entsprechen. Wenn allerdings das Bild nicht vorhanden ist, soll die Fläche 100 x 100 sein.

Beim dritten Aufruf wird dann nur eine 100 x 100 Fläche erzeugt.

>>>>>>>>>>>>>>

Das Problem sehe ich bei dem zweiten Aufruf.
Woher weiß die Prozedur, dass ich keine Angaben gemacht habe, wenn
ich Höhe und Breite mit

Code: Alles auswählen

Procedure LadeBild(Name$,breite=100,hoehe=100) 
Deklariere? Wenn mein geladenes Bild 200 x 200 zum Beispiel ist,
soll es ja auch 200 x 200 sein. Ansonsten würde ich wie oben angeben:
LadeBild(Name$,100,100) dann würde es gleich auf 100 x 100 gezerrt.

Ich möchte aber auch nicht das Bild mit LadeBild(name$,200,200) aufrufen müssen. Denn dazu muss ich ja bei jedem Bild erstmal seine Abmessungen kennen.

/:->
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

du brauchst doch nur nie eintretenden Parameter als Standard definieren, und dann innerhalb der Procedure entscheiden was du daraus schlussfolgern kannst:

ggf. bitte Anpassen

Code: Alles auswählen


Procedure LadeBild(Name$="",x=-1, y=-1)
 If Name$
  Bild = LoadImage(#PB_Any, Name$)
  If Bild
   If x>-1 And y>-1
    Bild = GrabImage(Bild, #PB_Any, 0, 0, x, y)
   EndIf 
   ProcedureReturn Bild
  EndIf
 EndIf
 If x=-1 And y=-1
  Bild = CreateImage(#PB_Any, 100, 100)
  ProcedureReturn Bild
 Else
  Bild = CreateImage(#PB_Any, x, y)
  ProcedureReturn Bild 
 EndIf
EndProcedure
 
LadeBild(Name$,100,100) 

LadeBild(Name$) 

LadeBild() 
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

Kein schöner Programmierstil, aber ich verstehe, was du meinst.

:allright:

Der Befehl ProcedureReturn sollte in einer Prozedur nur einmal und auch nur ganz zum Schluss der Prozedur vorkommen.

Aber die PureBasic-Hilfe ist da auch widersprüchlich.
Unter dem Punkt Prozeduren ...
sind zwar alle Beispiele sauber abgeschlossen, gleichzeitig wird aber im Hilfetext die Option schön geredet, dass man ProcedureReturn überall in einer Procedure aufrufen kann.

Wie gesagt: Dank dir. So hat halt jeder seinen Programmierstil :allright:
Kinder an die Macht http://scratch.mit.edu/
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

Xaby hat geschrieben:Der Befehl ProcedureReturn sollte in einer Prozedur nur einmal und auch nur ganz zum Schluss der Prozedur vorkommen.
...sagt wer? :?
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Antworten