OOP für Anfänger - Einstieg mit nachvollziehbarer Erklärung

wie baut man ein Objekt überhaupt auf, inkl. aller Variablen und Methoden, was sollen die :: und die . und die -> die man so häufg sieht, was ist eine Instanz, wie instanziiert man, wie vererbt man, wie zerstört man es, und all das in kleinen Häppchen und Schrittchen?
(und alles plattform-neutral)

PS,
das soll ntl keine Auftragsarbeit an dich persönlich sein, sondern quasi etwas, was in so einem gesuchten, fertigen Tutorial oder Lehrbuch enthalten sein müsste

EDIT
Beitragstext entfernt.

Dar offensichtlich nicht sachdienlich/erwünscht.

Die ganze constexpr-Benutzung muss ich mir nochmal tiefer zu Gemüte führen. Die Grundlagen sind mir bekannt, ich hätte es aber nie so weit ausbauen können. Evtl. war/ist da noch eine innere Schranke (ich komme von JAVA-OOP).
Ich finde es genial von Dir, wie Du mit Deinen Pins arbeiten kannst, ohne Flash/RAM dafür zu brauchen.

Wofür ist der OpenDrain am Arduino gut? Ich dachte das wären alles Gegentaktausgänge oder habe ich da etwas übersehen?

Gruß Tommy

Wofür ist der OpenDrain am Arduino gut? Ich dachte das wären alles Gegentaktausgänge oder habe ich da etwas übersehen?

Sehr gute Frage!

Natürlich sind das Gegentakt Ausgänge, oder Push-Pull Stufen.

Aber dennoch gibt es Situationen wo man einen Open Drain Ein und Ausgang braucht oder brauchen würde.
Typische Beispiele sind (Soft)I2C die ganzen 1 Wire Dinger z.B. die DS18S20 Thermometer, oder auch einige sonstige Sensoren.

Die OpenDrain Klasse bietet eine Schnittstelle, um die eigentliche Push-Pull In-Out Stufe, von der sie erbt, wie ein Open Drain nutzen zu können. Sie kapselt die Funktionalität soweit, dass keine Fehlbedienung Ausgang gegen Ausgang arbeiten lassen kann.

Eigentlich ein gutes Beispiel für "So geht OOP".
Man abstrahiert die Funktionalität des Pins, so wie er ist.
Man abstrahiert die Funktionalität eines OpenDrain Pin.
Und dann schafft man einen Adapter/Spezialisierung, welche dann genau das tut, was man möchte. Hier über die Vererbung und Spezialisierung so geschehen.

Kapselung als Sicherheitsmerkmal.

Wenn ich mir den OpenDrain-Pin richtig angesehen hätte (mein Fehler), hätte ich es sehen müssen, dass Du durch die Umschaltung auf Eingang den HIGH-Zustand abfängst und damit den Pin nach Außen wie einen OpenDrain/OpenCollector wirken lässt.

Gruß Tommy

Tommy56:
Wenn ich mir den OpenDrain-Pin richtig angesehen hätte (mein Fehler), hätte ich es sehen müssen, ...

Danke für die Frage, die Antwort hat mir Zeit gespart.

combie:
Klaus_ww und agmue haben sich genau schon auf diesem Wege versucht der OOP zu nähern.
Aber das "Warum" dabei nicht gefunden. Das dürfte ihr Unwohl sein damit erklären.

Ja, zumindest könnte es für mich zutreffen.

Das Beispiel ist ein paar Stufen oberhalb meines Niveaus. Nun denn!

Ich habe libraries\CombiePin\CombiePin.h angelegt, weil die IDE keine zwei Fenster zuläßt. Sind Probleme zu erwarten?

Combie::Pin::OutputPin<LED_BUILTIN>

Combie: Kommt vom namespace?
Pin: namespace oder Klasse, ich tippe auf namespace?
OutputPin: Klasse?
LED_BUILTIN auf den Prozessor bezogene Konstante der IDE?
<>: warum spitze Klammern? Liegt das am Template?

Was ist BuiltInLed? Eine Abkürzung, weil auch Combie::Pin::OutputPin<LED_BUILTIN> led; ginge, aber zu lang wäre?

Zu CombiePin.h:

isHigh() const erstaunt mich, wieso const?

Bei class InputPin ist doch alles öffentlich, ginge auch struct?

Jetzt bin ich ermattet, freue mich auf Antworten, gerne auch kurz.

LED_BUILTIN ist eine Konstante für die eingebaute LED, die in den prozessorspezifischen Dateien der IDE definiert wird.

Gruß Tommy

const Methoden können ihr Objekt nicht verändern. Es sei den die entsprechende Variable ist als mutable deklariert

Das const gehört außerdem zur Methoden Signatur. Dadurch kann man zwei Methoden gleichen Namens haben und unterschiedliche Versionen haben je nachdem ob das Objekt selbst (oder eine Referenz darauf) const ist oder nicht

class Test
{
private:
  int var = 5;
public:
  void foo() const{
    Serial.println("foo const");

    //var = 6;   //Fehler!
  }

  void foo() {
    Serial.println("foo");
  }
};

void setup()
{
  Serial.begin(9600);

  Test test;
  Test& ref = test;
  const Test& const_ref = test;

  ref.foo();
  const_ref.foo();
}

void loop()
{
}

Der Rückgabe-Wert gehört nicht zur Signatur! Dadurch kann man unterschiedliche Dinge zurückgeben je nachdem ob es verändert werden kann oder nicht

Ansonsten ist es einfach etwas mehr Sicherheit und Kontrolle darüber was den Zustand des Objekts ändern kann

Ob man dieses schreibt:

using BuiltInLed = Combie::Pin::OutputPin<LED_BUILTIN>;

BuiltInLed led;

Oder so:

Combie::Pin::OutputPin<LED_BUILTIN> led;

Oder so:

using namespace Combie::Pin;

OutputPin<LED_BUILTIN> led;

Macht in dieser Anwendung erstmal keinen wirklichen Unterschied.

Irgendwo in den Arduino Dateien findet sich ein
#define LED_BUILTIN 13

Beim ESP auch mal
#define LED_BUILTIN 2

Version A generiert einen neuen Datentype. Sinnvoll, wenn man ihn häufiger nutzen möchte. Es fasst nur diese Klasse an.
Version B "greift" in den Namensraum um eine einzige Klasse anzufassen
Version C importiert den gesamten Namensraum, mit allen Bezeichnern in den Namensraum der Anwendung.

So hat man drei Möglichkeiten sich eine Instanz von OutputPin zuzulegen.
Wie schon gesagt, der Weg ist vielfältig.
Das, was man konkret erreichen möchte, bestimmt, welcher Weg der bessere, schönere ist.

Hier dreht es sich einfach nur darum, in die Namespace Kiste rein zu greifen um da eine der Klassen an den Haken zu bekommen, um sie zu nutzen.

<>: warum spitze Klammern? Liegt das am Template?

Richtig.
Das ist der Template Parameter. Der Parameter ist Teil, des Types, der Klasse.

Auf dem Wege injiziere ich die Arduino Pinnummer in die Klasse, so dass eine spezialisierte Instanz entsteht.
Hier kann man das so tun, da die Pin Nummer eine feste Abhängigkeit ist.
Die LED wird nicht aus freien Stücken den Pin wechseln. Sie ist dort angelötet/gesteckt.
Auch spart es mir einen eigenen Konstruktor.

Der Vorteil:
Ich muss sie nicht als (konstante)Eigenschaft im Objekt halten.
So benötigt sie keinen Speicher.
Es erlaubt dem Kompiler die Instanz weg zu optimieren, da leer, keine Eigenschaften.

Ich nenne die Variablen/Konstanten eines Objektes/Klasse "Eigenschaften".
Im Englischen wird es auch mal "attributes" genannt.
Oder Member Vars

Templates sind eigentlich kein OOP Sprachmittel.
Sie existieren völlig losgelöst davon.
Und ja, hier ist es verschmolzen.

isHigh() const erstaunt mich, wieso const?

Wie ich dazu neige, Dinge möglichst zu verbergen, setze ich auch alles const, was man const machen kann.
Einerseits haut mir der Kompiler das dann um die Ohren, wenn ich es doch verändern will, und andererseits hilft man so auch dem Optimizer, die Dinge schlank zu machen.
Es ist teil der Denke.
Einen Teil der Begründung hat Serenifly ja schon gebracht.

Bei class InputPin ist doch alles öffentlich, ginge auch struct?

Vermutlich ja.
Noch nicht getestet.

Es ist mein gnadenloser Hang, interne Dinge zu verbergen, welcher mich eher dazu treibt class zu verwenden, als struct. Struct, nur für reine Datenbereiche, welche keine Methoden beinhalten. OK, einen Konstruktor, ok. Aber mehr auch nicht.

combie:
Ich glaube, das die Ausrichtung deiner Erwartungshaltung einem Lernerfolg entgegen steht.

Klaus_ww und agmue haben sich genau schon auf diesem Wege versucht der OOP zu nähern.
Aber das "Warum" dabei nicht gefunden. Das dürfte ihr Unwohl sein damit erklären.

Die Details, "Wie" man etwas tut, ist eher zweitrangig. Es gibt meist mehrere Möglichkeiten.
Das "Warum" ist viel spannender.

Das lernen des "Wie" ist viel interessanter, oder überhaupt erst fruchtbar, wenn das "Warum" begriffen ist.

Bedenke:
OOP ist nicht einfach eine andere Art Schlüsselworte/Token aneinander zu reihen, sondern eine andere Art zu denken, die Welt anders zu sehen. Das schlägt dann auch auf Bereiche des Quellcodes durch, welches nicht nur dieses OOP zugeordneten Token betrifft. Weder namespaces, noch templates, Operatorenüberladung oder constexpr haben zwangsweise was mit OOP zu tun. Sind aber Mittel um dem gesamten Programm die OOP Sicht/Weltanschauung/Philosophie aufzudrücken.

Also, keine Sorge:
Die Details werden sicherlich auch noch kommen...
Aber nur am Rande, und wenn, dann hauptsächlich mit dem Fokus auf das "Warum so und nicht anders".

Beispiel, "Instanz":
Wie soll ich den Begriff "Instanz" erklären, wenn es doch keine Instanz in der CombiePin gibt.
Klar instanziiere ich Objekte. Aber der Kompiler merkt, dass er sie vollständig verwerfen kann.
Was er dann auch tut.

Der Begriff "Instanz" wird erst wichtig, wenn sie existieren und man sie durch die Mühle dreht.

ok, ich sehe schon, compiepin ist nicht der richtige Einstieg in die OOP für mich, ich verstehe absolut keine Zeile.
Ein Schritt-für-Schritt-Tutorial mit sehr einfachen aufeinander aufgebauten beispielen wäre sicher besser als Einstieg für mich.
Wenn jemand eines kennt...?

Hallo,

du solltest noch dazu sagen das es egal ist ob man class oder struct verwendet. Nur der Zugriff auf privat und public sind unterschiedlich defaultmäßig gesetzt wenn man es nicht angibt. Wenn man privat und public immer angibt kann man das Wörtchen class und struct beliebig austauschen.

@ dsyleixa:
Das ist auch nichts was man nebenbei aus der Kalten heraus lernt. Man sollte Begriffe wie Objekte, Instanzen, Methoden usw schon kennen. Die praktische Anwendung und Kombinationsmöglichkeiten abseits von Büchern zeigt hier combie Eindrucksvoll. Das baut darauf auf. Das ist auch für mich schwer den Überblick zubehalten. Mal ganz nüchtern betrachtet schreibt combie eine nicht ausgelagerte Lib im Sketch. Mit wenigen Handgriffen könnte er eine Lib daraus machen.
Wenn du zum Bsp. die Bounce 2 Lib nutzt und mehrere Taster "definierst", dann erstellst du für jeden Taster ein eigenes Objekt. Diese Objekte nutzen alle die gleichen Funktionen (sprich Methoden) die in der Lib vorgesehen sind. Manche sind nach außen zugänglich und manche nicht. Du nutzt demnach schon OOP ohne es konkret zu wissen. Oder Du hast einen Mega2560 wie ich und nutzt alle 4 seriellen Schnittstellen mit Serial.begin, dann hat man 4 Objekte der seriellen erstellt, alle haben die gleiche Funktionalität, behindern und beeinflussen sich aber nicht gegenseitig weil alle Objekte für sich gekapselt sind. Es wurde einmal Code geschrieben der dann 4fach genutzt wird.

Wenn du nach OOP Anleitungen suchst wirst du fündig. Man findet dann meistens Ausarbeitungen von Studenten für ihre Abschlussarbeit. Ob das alles 100% geprüft ist weiß man nicht. Nüchtern betrachtet steht nicht mehr drin wie in Büchern. Nur das man tausend unterschiedliche Bsp. sieht.

Sorry für die Unterbrechung. Weitermachen - ich lese mit.

@ dsyleixa:
Das ist auch nichts was man nebenbei aus der Kalten heraus lernt. Man sollte Begriffe wie Objekte, Instanzen, Methoden usw schon kennen. Die praktische Anwendung und Kombinationsmöglichkeiten abseits von Büchern zeigt hier combie Eindrucksvoll. Das baut darauf auf. Das ist auch für mich schwer den Überblick zubehalten. Mal ganz nüchtern betrachtet schreibt combie eine nicht ausgelagerte Lib im Sketch. Mit wenigen Handgriffen könnte er eine Lib daraus machen.

da muss ich leider widersprechen - das von mir gesuchte Tutorial müsste eben GANZ vorn anfangen, mit den allerersten grundlegendsten Basics, und alles erklären, was, wie und wozu - und sich dann voran arbeiten, wie bereits geschrieben, denn mit dem obigen fertigen combiepin Code kann ich überhaupt nichts anfangen und erst recht nichts draus lernen.

Danke für die Antworten :slight_smile:

Mich reizt ein Vergleich, Beispiel aus #17:

</sup> <sup>Der Sketch verwendet [color=teal]3604[/color] Bytes (11%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes. Globale Variablen verwenden 9 Bytes (0%) des dynamischen Speichers, 2039 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.</sup> <sup>

Mein Programm:

void setup(void)
{
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop(void)
{
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  delay(1000);
}

</sup> <sup>Der Sketch verwendet [color=red]3964[/color] Bytes (12%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes. Globale Variablen verwenden 9 Bytes (0%) des dynamischen Speichers, 2039 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.</sup> <sup>

Um es mit Kermit zu sagen: "Applaus, Applaus!" combie kann es besser als die Programmierer der IDE!

combie:
Meine Hoffnung ist, dass sie nach dieser "Unterhaltung" noch besser sein wird.

Für Lernende wäre eine namentliche Unterscheidung von namespace und class Pin möglicherweise hilfreich.

combie:
Vermutlich ja.
Noch nicht getestet.

template<byte arduinoPin>
  struct OutputPin : protected Pin<arduinoPin>
  {
      using Pin<arduinoPin>::toggle;
      using Pin<arduinoPin>::isHigh;

struct anstelle class scheint auch zu funktionieren.

Wenn ich hier nach struct frage, möchte ich nur überprüfen, ob ich es verstanden habe.

Ein paar Detailfragen schenke ich mir, da wir das "Warum" ja nicht aus den Augen verlieren wollen. Ich bin gespannt auf Lektion 2.

Hallo,

wie schon erwähnt, ohne Angabe von privat und public kann man immer class gegen struct austauschen. Umgekehrt gehts nicht sorglos. Tauscht man struct gegen class wird alles defaultmäßig privat. Man wird Zugriffsfehler bekommen. Wenn man privat und public immer angibt, kann man jederzeit class und struct beliebig austauschen.

Im Grunde könnten doch die C++ Macher eins von beiden ersatzlos streichen wenn sie keine Rückwärtskompatibilität erhalten müßten? Theoretisch korrekt?

du solltest noch dazu sagen das es egal ist ob man class oder struct verwendet. Nur der Zugriff auf privat und public sind unterschiedlich defaultmäßig gesetzt wenn man es nicht angibt. Wenn man privat und public immer angibt kann man das Wörtchen class und struct beliebig austauschen.

Ok...
Eigentlich ist das eins der Details wo ich nicht unbedingt ran wollte...

Geschichtlich gesehen, ist struct älter.
Das erste "C mit Klassen" verwendete struct um die Daten zu halten/benennen und FunktionPointer(in der Struktur) um auf die Methoden zu zeigen. this war nur ein Zeiger auf die Struktur.

Damit konnte man schon viel machen!

Dann wurden die OOP Token der Sprache hinzugefügt.
So wurde dann aus "C mit Klassen" das C++

class ist wenig mehr, als ein um die Schlüsselworte public und private auf geblasenes struct.
Mit dem Unterschied, dass in struct alles per Default public ist, und bei class private.
Ansonsten voll austauschbar.


EDIT
Beitragstext teilweise entfernt.

Dar offensichtlich nicht sachdienlich/erwünscht.


Dann fange ich mal ganz vorne an:
Verstehen, was die drei Buchstaben OOP bedeuten.

OOP
O - wie Objekt
O - wie orientierte
P - wie Programmierung

Es heißt also ausgeschrieben: " Objekt orientierte Programmierung "

Bemerke:
Da steht nicht "Programmierung mit Objekten"!

Zu dem Wort Objekt findet sich bei Wikipedia u.A.:

Sache
Gegenstand

In unserem Fall sind das oft Abbilder, von real existierenden Dingen, in unserer Programmiersprache. Aber auch künstliche/abstrakte Modelle sind möglich. Vergleiche mit Gemälden.

Wikipedia sagt zu orientiert/Orientierung u.A.:

Orientierung (mental), eine kognitive Fähigkeit, die die Orientierung eines Subjekts in Zeit, Raum und bezüglich der eigenen Person umfasst

Dieses bezieht sich wirklich und vollständig auf das "Ich" in der Welt.
Wie das Ich die Welt sieht.
Das Ich sieht/baut Modelle von real existierenden Sachen/Dingen, und auch von Fantasiegebilden. Dann gießt das Ich diese Modelle in Strukturen.

Wikipedia Programmierung:

Programmierung (von altgriechisch πρόγραμμα prógramma „öffentlich und schriftlich bekannt gemachte Nachricht, Befehl“)[1] bezeichnet die Tätigkeit, Computerprogramme zu erstellen. Das ist ein Teilbereich der Softwareentwicklung[2] und umfasst vor allem das Umsetzen (Implementierung) des Softwareentwurfs in den Quellcode einer Programmiersprache.

Schlussfolgerung daraus:
OOP hat nichts mit irgendeiner bestimmten Programmiersprache zu tun.
Andersrum wird ein Schuh draus.
Unser C++ unterstützt die OOP im Sprachumfang.
Das erleichtert es, die OOP Denke in Code umzusetzen.

Man kann in jeder Programmiersprache Objekt orientiert programmieren!
Denn die Orientierung findet in einem selber statt.
Es ist eine reine Kopfsache.

An Sprachmitteln, verwendet man einfach das, was man vorfindet.

Übrigens:
Früher nannte man das, was heute "Methode aufrufen" heißt, "Nachricht senden".
Die alte Form hat auch seinen Reiz.
Es scheint mir natürlicher zu sein. (natürlicher im Sinne der OOP)


Ein bisschen sind Objekt orientierte Programmierer wie kleine Kinder. Die Blagen nehmen sich einen Bauklotz, schieben den über den Teppichboden und rufen "Brummm, Brummm, Brummm".
In der Vorstellung des Kindes und des OOProgrammierers ist der Holzklotz dann ein Auto!
Nix Räder dran, aber Auto.

Der OOProgrammierer kümmert sich nicht um Räder, wenn er nicht muss.
Wenn ein Modell ohne Räder reicht, dann gut, dann eben ohne Räder.

Orientierung auf die Sache!
Modellbildung.
Die vollständige Realität kann man sowieso nicht im Computer abbilden. Denn dann müsste der Computer wohl größer sein, als die Realität. Da er aber meist Teil der Realität ist... kann man sagen, dass man die vollständige Realität nur in einem irrealen Computer abbilden kann.

Der Prozedurale Programmierer, der malt Programmlaufpläne!
Der interessiert sich für "Wann wird Was und womit getan?"
Der Fortgeschrittene hat gemerkt, dass das nicht reicht, und malt Datenflussdiagramme.
Und kommt so auf den Trichter, dass z.B. Schleifen oft völlig überbewertet werden.

Der Objekt orientierte Programmierer schaut auf die Dinge/Modelle und auf die Beziehungen zwischen den Dingen/Modellen. Flussdiagramme benutzt er nur, wenn er Methoden baut.

Schlussfolgerung daraus:
Ja, ist ist völlig ok, und sicherlich Ziel führend, die OOP Merkmale der verwendeten Sprache zu lernen.
Aber es ist noch viel wichtiger, die Denke auszurichten, im sinne von "Orientierung finden".

Und hier eben mit der Orientierung auf Sachen/Gegenstände/Modelle und deren Beziehungen untereinander.

combie:
Aber es ist noch viel wichtiger, die Denke auszurichten, im sinne von "Orientierung finden".

Genau das ist das schwierige, wenn man Jahre lang prozedural programmiert hat. Man muss lernen, die Probleme von einer völlig anderen Warte aus zu sehen.
Ich habe diesen Wechsel des Denkens von ANSI-C zu JAVA machen müssen. (Ich hatte vorher mal eine kleine OOP-Exkursion in Turbo-Pascal gemacht).

Das Umdenken ist schwieriger, als wenn man es neu als OOP lernt.

Gruß Tommy

Das Umdenken ist schwieriger, als wenn man es neu als OOP lernt.

Die Frage ist da nur:
Wie bekommt man es hin, die gewohnten Denkpfade zu verlassen?

Von mir selber weiß ich, dass der Umschwung, ohne den Geistesblitz mit den Bienen, vermutlich sehr zäh geworden wäre, bis unmöglich.

Alles in einem sperrt sich dagegen, die prächtigen, und vor allen dingen erfolgreich genutzten Wege zu verlassen.

Wie war das bei dir?
Irgendwelche Stellen, wo es "klick" gemacht hat?


Eigentlich, soweit ich bisher feststellen durfte, fängt man heutzutage in Ausbildungen welche in die OOP Welt führen(können) mit UML Diagrammen an. Denn diese lenken von Anfang an die Aufmerksamkeit auf die Dinge und auf ihre Beziehungen untereinander.


Um es mit Kermit zu sagen: "Applaus, Applaus!" combie kann es besser als die Programmierer der IDE!

Danke für die Blumen!

Ich muss dabei aber auch zu bedenken geben, dass die Arduino Entwickler gänzlich andere Ziele verfolgt haben.

Soll auf Dutzenden Plattformen laufen.
Weitgehende Kompatibilität mit Processing
Übergabe der Arduino Pinnummer zur Laufzeit
Abschalten des PWM auf dem Pin

Alles das kann meine Klasse nicht leisten.
Aber dafür ist sie ca 25 mal so schnell, und erheblich schlanker (im Kompilat).
Bei deinem Beispiel sogar 50 mal so fix.
(fällt nur wegen dem delay() nicht auf)

Der Vergleich hinkt also recht stark.

Bei mir waren es eigentlich 2 Stellen.
Jahre bevor ich es im Job gebraucht habe, habe ich mal mit Turbopascal unter DOS/Win 3 eine grafische Steuerung für x Eingangsspannungen und y Relais gebaut, die sich der User mit der Maus aufbauen konnte und die anschließend auch gemessen und gesteuert hat.

Das wäre prozedural wohl eine Katastrophe geworden, also habe ich mich hin gesetzt und mir ein eigenes Set an Klassen überlegt und diese von "Object" an aufgebaut. Als das Ding dann lief, hatte ich wohl einiges an OOP verstanden. Das Ganze war eher eine Beschäftigung für mich selbst, um nicht einzurosten, als ich mal 1 Jahr arbeitslos war.

Danach habe ich lange Zeit fast nur noch prozedural gearbeitet (ANSI-C und PL/SQL auf HP-UX).
Dann kam der zweite Teil. Die Software sollte eine Weboberfläche bekommen. Ich war der letzte "Überlebende" der alten Software und sollte dann auch die Wartung und Weiterentwicklung der neuen Software übernehmen. Ich habe also dann viele Jahre sowohl objektorientiert (JAVA und Co.), als auch prozedural (PL/SQL) zeitgleich nebeneinander in der gleichen Anwendung genutzt/bearbeitet. Solange bis ich in den Freizeitblock der Altersteilzeit gegangen bin.

Im Endeffekt war es also eher der äußere Zwang mich mit JAVA und OOP tiefer zu beschäftigen.

Gruß Tommy

Hi Jungs,

irgendwie ist das starker Tobak für mich.
Muss das mal in einer ruhigen Stunde durchkauen, also den Code neben Combies Erläuterungen legen und versuchen zu verstehen.

Grob umrissen hab ich wohl mittlerweile das Konzept der OOP, aber fühle mich noch wie in Fisch im Trüben. Da fällt sicher aber noch der Groschen.

Seid also nachsichtig mit mir, ich brauch da meine Zeit. Aber da ich das Thema angeleiert habe bleib ich auch dran. Bis zum Erfolg 8) oder zur frustrierten Aufgabe :sob:

Nix mit Aufgabe. Du kannst doch fragen, wenn Du etwas nicht verstehst. Das ist doch der Sinn dieses Threads. So hautnahe Möglichkeiten zu Rückfragen bekommst Du nie wieder.

Gruß Tommy