Seite 1 von 1

Wie geht ihr mit Überladung um?

Verfasst: 20.12.2022 16:37
von s91
Was hat PureBasic zu bieten um Überladungen zu "simulieren"?

Das Überladen einer Prozedur bedeutet, sie in mehreren Versionen zu definieren, wobei derselbe Name, aber verschiedene Parameterlisten verwendet werden. Der Zweck der Überladung besteht darin, mehrere eng verwandte Versionen eines Verfahrens zu definieren, ohne sie nach Namen unterscheiden zu müssen. [...]
von: https://learn.microsoft.com/de-de/dotne ... verloading

Daraus dass PureBasic keine Überladung ermöglicht, schlussfolgere ich:

- die unterschiedlichen Verfahrensversionen müssen per Namen unterschieden werden, es sei denn es ermöglichen sich bedingte Teilverfahren per optionalen Parametern (was aber einen gehörigen Unterschied zur Überladung darstellen kann)
- enge Verwandschaft zwischen Verfahrensversionen kann umständlicher geschaffen werden, indem alle Parameter außerhalb der Funktion (etwa "global") festgeschrieben werden und die Funktion selbst dann alle Fallunterscheidungen unternimmt um die Datenlage zu klären (zum Beispiel: untersucht, was alles bei #null oder #empty$ steht).

Für letzteren Punkt gibt es da eine Problematik: alle Parameternamen müssen ja innerhalb eines die Funktion umgebenden Namensraumes erkennbar definiert sein (außer bei Kleinstprogrammen) und in die Funktion eingebunden werden. Was ist dafür besser, "global" oder "shared", bzw. gibt es da überhaupt einen zu beachtenden Unterschied?

Hattet Ihr mal Fälle in denen Soetwas relevant wurde und wie seid Ihr damit umgegangen? Und: Könnte man auf Maschinencodeebene feststellen, dass es herstellergemachte Geschwindigkeitsunterschiede zwischen VBs Überladungen und PBs expliziteren Wegen gibt?

Re: Wie geht ihr mit Überladung um?

Verfasst: 20.12.2022 17:29
von STARGÅTE
Um vielleicht etwas besser darauf antworten zu können wäre meine Gegenfrage, welches Beispiel schwebt dir gerade vor?

Zu deinem ersten Punkt besteht in PureBasic ja die Limitierung, dass es gar nicht möglich ist, im gleichen Parameterindex verschiedene Typen zu übergeben: Zahl, String, Liste, Map, Array usw.
Somit ist das schlichtweg so gar nicht möglich.
Zu deinem zweiten Punkt würde ich stark davon abraten die Prozedur nur als Caller zu nutzen und Globale Variaben als Parameter zu nutzen. Grund ist, dadurch fallen so simple Sache wie Rekursion weg.

Ich selbst habe das Überladen in PureBasic dadurch "simuliert", dass ich im Endeffekt immer nur Pointer zu den "Objekten" übergeben habe und das Objekt selbst Infos darüber trug was es ist.
s91 hat geschrieben: 20.12.2022 16:37 Könnte man auf Maschinencodeebene feststellen, dass es herstellergemachte Geschwindigkeitsunterschiede zwischen VBs Überladungen und PBs expliziteren Wegen gibt?
Definitiv. Soweit ich das richtig verstanden habe, sind echte Überladungen ja auf Kompiler-Ebene, dass heißt, beim kompilieren wird sich schon je nach Type des Parameters für eine Version entschieden. In PureBasic wäre das immer erst zur Laufzeit möglich für Abfragen.

Alternativ kann man aber Macros nutzen, die alle Versionen sozusagen umhüllen und dann zur Compilerzeit die passenden finden. Das geht dann aber auch nur sehr eingeschränkt:

Code: Alles auswählen

Macro MyPrintN(param)
	CompilerSelect TypeOf(param)
		CompilerCase #PB_String
			PrintN(param)
		CompilerCase #PB_Integer
			PrintN(Str(param))
		CompilerCase #PB_Float
			PrintN(StrF(param))
	CompilerEndSelect
EndMacro


Define MyString.s = "Hallo"
Define MyInteger.i = 123
Define MyFloat.f = 3.14

OpenConsole()
MyPrintN(MyString)
MyPrintN(MyInteger)
MyPrintN(MyFloat)
Input()

Re: Wie geht ihr mit Überladung um?

Verfasst: 20.12.2022 23:06
von jacdelad
Ich denke, die einzige und recht einfache Variante ist, es wie bei den Windows APIs zu machen: Einen strukturierten Speicherbereich definieren, in das erste Element die Größe/Version eintragen und dann die entsprechenden Werte. Der Bereich ist somit von Version zu Version erweiterbar. Das ist zwar keine echte Überladung in dem Sinn, aber genauso nutzbar.

Re: Wie geht ihr mit Überladung um?

Verfasst: 21.12.2022 15:19
von NicTheQuick
...womit man schon kurz davor ist OOP zu nutzen. Man hat strukturierte Objekte und übergibt diese den Prozeduren, die dann entscheiden, was mit dem Objekt getan werden muss. Die Fallunterscheidung kann man sich sparen, indem man Interfaces nutzt und für jeden Objekttyp gleich mitliefert welche Methode für ihn benutzt werden soll.

Noch ein Hinweise bezüglich der globalen Variablen. Neben dem von Stargate angesprochenen Problem der Rekursion hast du damit auch ein Problem mit Threads. Wenn du einfach jedes "Global" mit "Threaded" ersetzt, ist das aber gelöst. Rekursion geht dann aber immer noch nicht.