Klasse objekt functionen fragensammlung

Godstyle

Erfahrenes Mitglied
Moin Moin,

bin mir mal wieder die Haara am ausreißen, zumnindest wenn ich noch welche hätte.

Bin erneut an das Thema Klassen und functionen geraten und habe nur eines kapiert:

class functioniert nicht
{
var $dubistzublöd dafür

nun, was funktioniert nicht?

ich denke in erster Linie der Zusammenhang in meinem Kopf da sich für mich nach wie vor nicht der wirkliche Nutzen ableiten lässt.

Als bsp:

Ich bestimme die entfernung 2er Punkte anhand der jeweiligen x/y koordinaten (plz entfernung).

Vorgehen bisher, ich nehme beide user, suche deren PLZ und die dazugehörigen x/y koo und berechne die entfernung. Das ganze in einer eigenen PHP Datei die ich nach bedarf includiere.

So, jetzt will ich das mal mit Klassen und functionen realisieren.

Also nach 10 Aspirin und 3 std kopf zerbrechen setze ich mich mit KIppe und Kaffee voller Tatendrang an meinen Rechner, tippe ein Class entfernung ....
mhmm nicht gut also neu: function neueStrecke ().

Zunächsteinmal wollte ich nur den zusammenhang von Klasse, Objekt und function kennen lernen daher etwas ganz einfaches:
PHP:
<?php
class user
	{
		var $ort;
		
			function ort($gort)
			{
				$u_ort = $gort; //ort aus DB nach Angezeigter User
				$this->ort= $u_ort;
				return $this->ort;
			}
	}
	
	
class entfernung extends user
	{
		var $distanz;
		
		function strecke($strecke)
		{
			$this->meinort="5";

			return $this->meinort;
		}
		
		function neueStrecke()
		{
		$this->ort=$this->ort / $this->meinort;


		return $this->ort;
		}
	}
		


$nutzer = new entfernung;
$user= $nutzer->ort("20");
$entfernung= $nutzer->strecke("5");


$neueStrecke = $nutzer->neueStrecke();


echo "$neueStrecke";


ok, zugegeben die Namen sind wirklich nicht clever gewählt jedoch berechnet er mir das richtige, nur Sinnvoll?

Frage 1: Was in eine Klasse packen?
Da stehe ich dann direkt an dem Hauptproblem, was sollte in eine classe rein, der erste Gedanke ich habe eine User klasse, in der sind alle funktionen gesammelt wie als freund hinzufügen, anschreiben, ignorieren, entfernung berechnen etc.
Frage 2:
(zwischenfrage die sich stellte, lädt man die functionen alle mit oder ist es so das sie nur dann ausgelesen werden wenn sie aufgerufen wurden).

Frage 3: extends

extends = vererbung, so wie ich es verstanden habe und Mehrfachvererbung gibt es nicht.
Wie ist das genau gemeint?
gibt es das nicht:

class erste
class zweite extends erste
class dritte extends zweite

oder meinen die
class dritte extends erste,zweite?

oder gar beides nicht machbar?

Frage 4: aufruf der funktion
gut das ich das wiefolgt machen kann ist mir bewusst:
$nutzer = new entfernung;
$user= $nutzer->ort("20");
$entfernung= $nutzer->strecke("5");
$neueStrecke = $nutzer->neueStrecke();

nur wie stelle ich das dann an wenn ich auf einen link click reagieren soll? bsp: delate friend. bisher habe ich es über JS gelöst das bei onclick reagierte und dann die entsprechende PHP datei ausführte. geht das nun mit klassen auch so einfach? onclick(führe function einer Klasse aus)?
// Ja genügt sonst bitte kleine erklärung

Frage 5:

kann es sein das ich ein völlig falsches verständniss von Klassen habe und deswegen so dumme fragen stelle oder ist es normal das man anfangs davor steht wie ein neandertaler vor der Playstation?

So da ich euch hier keinen Roman schreiben möchte bitte ich um entschuldigung für die evt dummen fragen aber getreu dem Motto, wer nicht fragt bleibt dumm bin ich auf die antworten gespannt und mit weiteren gegenfragen muss zu rechnen sein.

lg
 
Uiuiui ;-)

Ich weiß noch nicht, wohin das führen wird, aber schauen wir mal. Da es etwas längere Beiträge werden, teile ich es auf mehrere Posts auf, der Übersicht halber. Die Mods mögen es mir verzeihen.

1. Klassen sind erstmal Baupläne für Objekte, so kann man sich das schon mal merken. Grundsätzlich kommt es darauf an, was du mit dem Objekt tun möchtest, nach dem du es aus einer Klassen-Definition (was anderes ist eine Klasse nämlich nicht) erzeugen lässt. In eine Klasse "User" kommt alles rein, was du mit einem User assoziierst. Wenn das der Name und bspw. eine Email-Adresse ist, dann erstellst du dafür die jeweiligen Properties (Eigenschaften) als Member-Variablen. So wie du es schon mit der Klasse User gemacht hast. Bei den Member-Variablen kann es sinnvoll sein, einen Teil oder alles mittels get-Funktion abholbar und mittels set-Funktion änderbar zu machen - je nach Zweck. In einigen Fällen macht es sinn, dem Objekt bereits bei der Erzeugung seine Werte für die Member-Variablen mit zu geben.

Das kann dann so aussehen:

PHP:
class User
{
  private $name;

  private $email;

  public function __construct($name, $email)
  {
    $this->name = $name;
    $this->email = $email;
  }

  public function getName()
  {
    return $this->name;
  }

  public function getEmail()
  {
    return $this->email;
  }
}

Damit ist die Klasse User schön übersichtlich und aufgeräumt. Wenn du mehr Informationen unterbringen willst, kann es ggf. sinnvoller sein, Vererbung anzuwenden, wie du das mit der Klasse entfernung gemacht hast. Das könnte man allerdings als "Person" definieren, die ja a) ein User-Konto und b) eine Adresse hat. Also vererben wir User zu Person und werden dann objekt-technisch etwas konkreter:

PHP:
class Person extends User
{
  private $plz;
  private $strasse;
  private $ort;

  public function Person($name, $email, $plz, $strasse, $ort)
  {
    parent::__construct($name, $email);
    $this->plz = $plz;
    $this->strasse = $strasse;
    $this->ort = $ort;
  }

  public function berechneEntfernungZu( Person $anderePerson )
  {
    // Hier die Kalkulation für die Entfernung anhand eines sinnlosen Beispiels
    $entfernung = CooleBerechnerKlasse::distanzLatLonZuLatLon( 
          OrtKlasse::getLatLon($this->plz),
          OrtKlasse::getLatLon($anderePerson->getPlz())
    );

    return $entfernung;
  }

  public function getOrt()
  {
    return $this->ort;
  }

  public function getStrasse()
  {
    return $this->strasse;
  }

  public function getPlz()
  {
    return $this->plz;
  }
}

Damit hast du die Entfernung an die Klasse Person gekoppelt, die eigentliche Geschäfts-Logik für das Berechnen kann man aber auf Helfer-Klassen (hier "CooleBerechnerKlasse" und "OrtKlasse") ausgelagert, was den Code wieder etwas übersichtlicher macht. Architektonisch kann man es sicher noch eleganter lösen, für diesen Fall belassen wir es jetzt aber mal dabei. Es sieht aufgeräumt und klar gegliedert aus.

Die anderen Funktionen wie "als Freund hinzufügen" oder "anschreiben" würde ich weder in User noch in Person hinzufügen, sondern erstmal überlegen, wo es logisch hingehört. Bspw. ein eine weitere Klasse "Social". Damit bleiben die anderen Komponenten lose und können prima an anderer Stelle wieder verwendet werden.

Einfacher Merksatz: Halte die Klassen so kurz wie möglich, erstelle lieber mehrere Ableitungen oder komplett lose Komponenten (wie die bereits erwähnten Hilfsklassen).
 
Hi

zuerst zu deinem Code:
Eine Variable und eine Funktion in User, die beide Ort heißen, ist nicht gut.
Und Entfernung sollte ja nicht von User erben.
Was Sinn macht ist eine Klasse Kraftfahrzeug, und davon erbend Pkw, Lkw, Motorrad, Traktor.
Warum? Weil diese vier Sachen alle Kraftfahrzeuge sind.
Ist die Entfernung "4 Kilometer" ein User (deiner Webseite)?
Und außerdem würde ich keine Klasse für Entfernungungen machen,
die sind nämlich nur eine einzige Zahl (also nicht mehrere Werte zum Zusammenfassen)
und können nichts "tun" (ein User kann sich anmelden, abmelden, Passwort ändern usw...,
aber was kann eine Entfernung?)
Wie wäre folgendes:
Klasse User
-function getKoordinaten
Klasse GeoBerechnung
-function entfernung(koord1,koord2)

Was was ist:
Eine Funktion ist ein Codeblock, der einfach einen Namen bekommen hat
und aus dem Hauptcode ausgelagert wurde.
Grund: Wenn man das Selbe 1000 mal machen will
muss man den ganzen Code nicht 1000 mal hinschreiben, nur den Namen.
Gut, bei 1000 komplett gleichen Durchgängen kann man auch einfach eine Schleife machen,
aber die Funktion kann man per Parameter etwas variieren.
Zeug mitgeben, jedesmal anders, das dann an den passenden Stellen
im ausgelagerten Code eingesetzt wird.
Und das war so ziemlich alles, ws Funktionen sind.

Eine Klasse wie User ist eine Zusammenfassung
von mehreren zusammengehörenden Variablen/Funktionen,
aber: Nur eine Vorlage davon.
In die Variablen kann man keine Werte speichern oder so.

Ein Objekt/Instanz einer Klasse ist dann einen tatsächliche Ausgabe der Klasse,
dh. alle Variablen der Vorlage existierend und die Funktionen aufrufbar.
Der eigentliche Sinn ist, dass man mehrere voneinander unabhängige Objekte haben kann.

...
Statt Variablen wie "user1name,user1ort,user1mail,user1passwd,
user2name,user2ort,user2mail,user2passwd,user3name,user3ort,user3mail,user3passwd"
zu machen, machst du eine Klasse "user{name,,ort,mail,passwd}"
und die Variablen "user1,user2,user3".
Arbeitserleichterung.


Zu den Fragen:
Frage 1: Klingt nicht schlecht.

Frage 2: Ganz von PHP unverarbeitet bleiben die Funktionen nicht,
auch wenn man sie nicht aufruft.
Aber zumindest wird nichts gemacht, was in der Funktion steht, falls du das meinst.

Frage 3: Wenn Mehrfachvererbung nicht erlaubt ist
ist Folgendes nicht möglich:
class A extends B,C,D

Folgendes ist Möglich
class A
class B extends A
class C extends A
class D extends A

und Folgendes ist auch möglich:
class A
class B extends A
class C extends B
class D extends C

Frage 4: Ja.
Wenn du über JS eine PHP-Datei anstarten kannst wird das gemacht,
unabhängig von Klassen oder nicht.

Frage 5: Normal...naja.
Zumindest gehts nicht nur dir so, das ist sicher
(wie man auch hier im Forum immer wieder merkt :))

edit: Och, 11 Minuten zu spät :D
edit2: Zumindest ich hab gar nicht dagegen, überlange Beiträge aufzuteilen,
und habs auch selbst schon gemacht.
 
2. Probier mal folgenden Code:

PHP:
<?php
class Blub
{
	function bla()
	{
		frlhsd();
	}
	
	function moep()
	{
		echo "fump";
	}

}

$b = new Blub();
$b->moep();

Wie man sieht, wird nur die Funktion moep() aufgerufen, bla() jedoch nicht. Daher wird der Code auch nicht ausgeführt und somit auch nicht angezeigt, dass es die Funktion "frlhsd()" gar nicht gibt. Versuch mal, statt moep() die Funktion bla() aufzurufen :-)

Anders verhält es sich allerdings bei Syntax-Fehlern:

PHP:
<?php
class Blub
{
	function bla()
	{
		frlhsd
	}
	
	function moep()
	{
		echo "fump";
	}

}

$b = new Blub();
$b->moep();

Wie man sieht, ist in bla() jetzt ein Syntax-Fehler drin. frlhsd ist jetzt weder eine Funktion (es fehlt die Klammer für eine Parameter-Liste) noch eine Zuweisung.

Wir fassen also zusammen: Der Parser analysiert den Code auf korrekte Syntax und führt dann dass aus, was programmatisch vorgegeben ist. Wenn in einer toten Funktion unsinnige Aufrufe oder Zuweisungen sind, wird das nicht aufgedeckt. Daher als Rat: Unittests ;-)
 
Nun denn, eure arbeit bleibt nicht folgenlos wie versprochen ;)


Also erstmal danke für die beiden langen Posts von euch auf die ich nun auch direkt eingehe:

@saftmeister:

"In eine Klasse "User" kommt alles rein, was du mit einem User assoziierst. "

ich fasse das nun so auf, das ich in diesem Fall, alles in cie class User reinpacke was ich immer brauchen werde, zB die userID, SessionID und den Berechtigungsstatus später wie "Admin" "gast" "member".

declarieren tue ich sie als private weil: (ist eine Frage) Sie mit public gesagt bekommen das sie nicht überschrieben werden können nach ihrer deklaration.

deklariert werden Sie in dem bereich public function __construct($name, $email) welches ich um die neuen werte erweitere.

Sprich im Bereich __construct gebe ich den variablen feste werte, dich ich in den functionen darunter ermittel.


_______________

code.php

hier greife ich auf die class User zu, da ich zum ermitteln der richtigen plz, str, ort ebenfalls die daten des Users brauche um ihn eindeutig zu identifizieren und den richtigen Datensatz ermitteln kann um die Berechnung anstellen zu können.

ich ermittel wieder über die public function getOrt() usw die neuen Variablen um diese dann bei der berechnung zu haben.

__ hierzu kommt mir anhand deines codes eine erste verunsicherung auf.

Du sagst: "// Hier die Kalkulation für die Entfernung anhand eines sinnlosen Beispiels
OrtKlasse::getLatLon($this->plz),"

OrtKlasse, ist dies eine erzeugte unterklasse die durch :: eingebunden wird? ich meine mich entsinnen zu können das ich durch :: eine function einer anderen Klasse aufrufen kann

was dadurch bestätigt wird was du im nächsten abschnitt sagst: "die eigentliche Geschäfts-Logik für das Berechnen kann man aber auf Helfer-Klassen " Also somit eine Klasse in einer Klasse weil ein weiteres extends nicht möglich wäre um diese Klasse gänzlich auszulagern.

Dein Merksatz steht nun auf einem POST IT an meinem Monitor ;)

Danke Dir an dieser Stelle schoneinmal und ich hoffe ich habe es richtig wieder gegeben, zumindest wollte ich so meine Denkart wiederspiegeln um die Fehler bei mir leichter zu verdeutlichen ;)



__________________________________________________________________________

@sheel:


"Eine Variable und eine Funktion in User, die beide Ort heißen, ist nicht gut."

Stimme ich vollkommen zu, habe ich im nächsten abschnitt bei mir auch direkt selbst bemängelt das die namen wohl äußerst schlecht gewählt wurden ;)


"Und Entfernung sollte ja nicht von User erben."
Ich habe diesen weg gewählt weil es mir logisch erschien das ich die Ort über die User am sinnvollsten ermitteln kann und diese brauche ich ja um darüber den Rest zu ermitteln.


"Ist die Entfernung "4 Kilometer" ein User (deiner Webseite)?"
Nein aber der Ort der mit dem User in direkter verbindung steht

"aber was kann eine Entfernung?"
Eine entfernung kann ermitteln welche User im Umreis von x km ist.


"Klasse User
-function getKoordinaten
Klasse GeoBerechnung
-function entfernung(koord1,koord2)
"

Absolut mit einverstanden


"Eine Funktion ist ein Codeblock, der einfach einen Namen bekommen hat
und aus dem Hauptcode ausgelagert wurde."

Also um grunde das selbe wie ein include mit wertübergabe?


"In die Variablen kann man keine Werte speichern oder so."
Grund ist das variablen namen nur innerhalb einer Klasse gültigkeit haben und auch nicht durch eine ausserhalb liegende deklaration verbelegt sind sofern der wert nicht über ein Objekt mitgeteilt wird.



Zu Frage 1: Danke
Zu Frage 2: Genau das wollte ich wissen
Zu Frage 3: Super auch das ist verstanden
Zu Frage 4: Akzeptiert
Zu Frage 1: Beruhigt mich ein wenig ;)


//EDIT 1 zu sheel:

"Klasse User
-function getKoordinaten
Klasse GeoBerechnung
-function entfernung(koord1,koord2)

sollte ich um dies zu realisieren zunächst beide user an die function senden:

PHP:
<?php
$u = new User;
$user= $u->getKoordinaten("user1"); //array mit x und y zurückliefern, alternative string mit _
$user2= $u->getKoordinaten("user2"); //array mit x und y zurückliefern, alternative string mit _

$g = new GeoBerechnung;
$entf = $g->entfernung($user,$user2); 

echo $entf;
 
Zuletzt bearbeitet:
public hat nichts damit zu tun, ob die Variablen änderbar sind oder nicht.
Mit private kannst du festlegen, dass die Variable nur von Funktionen
der selben Klasse geändert werden kann.
Wenn du irgendwo im Code eine Variable "$var = new meineklasse();" hast
und die Klasse meineklasse eine private variable pv hat kannst du jetzt nicht sowas machen:
"$var->pv = 4;". Was aber geht ist eine Funktion der Klasse aufzurufen,
die ihrerseits pv auf etwas ändert (wenn es so eine Funktion gibt)
Mit public-Variablen kann man alles von überall her machen.
Bei private verhindert man praktisch, dass einem irgendwer "dazwischenfunkt".

Ein Konstruktor gibt keine festen Werte, die dann geändert werden (sowas gibts nicht).
Ein Konstruktor ist einfach dazu da, irgendwelche "Vorbereitungen"
für ein gerade erstelles Objekt zu machen (automatisch beim Erstellen).
Um den User zu nehmen, es darf zB. keine User ohne Namen geben.
Dann kann man eine Konstruktorfunktion machen,
die als Parameter einen Namen bekommt (und ihn der passenden Variable zuweist).
Wenn man jetzt ein Userobjekt haben will "$bla=new user();"
muss man dem Konstruktor seine Parameter geben "$bla=new user("Heinz");"
weil sonst überhaupt kein Objekt erstellt wird (Prinzip zumindest)

extends ist NICHT dazu da, um Klassen aufgrund ihrer Größe aufzuteilen.
Zurzeit hab ich aber keine Ahnung, wie ich da gut erklären soll...

Ob 4km einer deiner User ist: Du sagst nein, das stimmt,
und damit erbt Entfernung nicht von User. Fertig.
Was einen User ausmacht ist nicht nur ein Ort,
und auch wenn: eine Entfernung ist auch kein Ort.

Wenn du unbedingt willst, mach eine Klasse Entfernung,
die einfach nicht von User extended.
(und wie schon gesagt macht eine Klasse Entfernung keinen Sinn)

Was sonst passiert:
Wenn deine Userklasse jetzt auch noch einen Namen, Passwort etc. bekommt
hat jede Enfernung plötzlich auch Name und Passwort.
Das macht doch überhaupt keinen Sinn.

Zu Funktion etc.:
"Also um grunde das selbe wie ein include mit wertübergabe?":
Kann man so sehen.

"Grund ist das variablen namen nur innerhalb einer Klasse gültigkeit haben und auch nicht durch eine ausserhalb liegende deklaration verbelegt sind sofern der wert nicht über ein Objekt mitgeteilt wird."
Nein.
Grund ist, dass es diese Variablen einfach nicht gibt.
Was im class-Bereich steht ist im Hausbau das, was ein Architekt aufs Papier zeichnet.
Wenn du da eine Küche siehst kannst du in der auch nicht kochen,
und kein Essen in die Schränke räumen.
Erst mit einem Objekt des Plans (ein gebautes Haus nach diesem Plan)
kann man das alles machen.
Klassen sind nur Vorlagen, und erst mit einem new... erstellst du ein Objekt,
das verwendbar ist.
 
Gut gut, einige DInge wurden erneut klarer, ich hatte den Post zuvor editiert. Warum ich die entfernung nicht in abhängigkeit setzen sollte ist nun völlig klar und mein denken diesbezüglich hat sich geändert ;)

"extends ist NICHT dazu da, um Klassen aufgrund ihrer Größe aufzuteilen.
Zurzeit hab ich aber keine Ahnung, wie ich da gut erklären soll..."

Ich denke das hast du, zuvor erledigt um bei meinem bsp zu bleiben würde ich sagen, das ich extands zB dafür verwende wenn ich eine User suche bauen würde, class Usersuche extands User weil ich ja einige functionen aus der User brauche getkoor get plz get alter usw...
oder liege ich da auch wieder daneben?
 
Wenn deine Userklasse eine Funktion getAlter hat wird die wohl dazu da sein,
dass man an anderen Codestellen (außerhalb von user zB.)
das Alter von User(-objekten) erfahren kann.

Wenn Usersuche von User erbt ist es per Definition ein User.
dh. auch die Suche hat ein abfragbares Alter.
Sinn dahinter?

Die Suche ist kein User, auch wenn sie User sucht. Sie ist einfach keiner.
Daher hat eine Suche auch kein Alter, keine PLZ, keine Freunde oder sonstwas.
Wenn irgendwo innerhalb der Suche User-Objekte (in Variablen) vorkommen
(zB. per Parameter übergeben) kann das getAlter von denen verwendet werden,
auch wenn die Suche nicht von User erbt. Dafür ist getAlter ja da,
für andere Klassen/Code generell zum Verwenden.

...
Da du mit der ganzen Sache sowieso noch sehr unsicher bist,
vergiss doch vorerst einfach mal, dass es extends überhaupt gibt.
Weg mit allem Vererbungszeug. Das kannst du dann lernen,
wenn du dich ohne dem auskennst.
 
Vererbung mal etwas konkreter, weil du ja offenbar Interesse hast, das zu verstehen:

Versuch dir Klassen wie Komponenten vorzustellen. Z.B. wie Teile um ein Fahrrad zusammen zu bauen.

Du hast bspw. eine Basis-Klasse "Bauteil".
Von dieser Basis-Klasse vererbst weitere Klassen wie "Rahmen", eine für "Rad", "Lenker" usw. Die einzelnen Klassen haben ihre spezifischen Eigenschaften wie "Rohstoff", "Farbe" usw.

In der Basis-Klasse gibt es eine Methode "zusammenbauen()". Das heißt, alle Bauteile erben diese Methode (sofern sie entweder public oder protected ist). Das bedeutet, du kannst jedes Bauteil zusammenbauen und daraus dann ein Fahrrad erzeugen, das alle relevanten Komponenten hat um damit fahren zu können.

Der Vorteil dieser Herangehensweise ist klar, sobald man anfängt sich darüber Gedanken zu machen, ob man einen Rahmen nicht etwas spezifischer beschreiben will. Dann kannst du nämlich eine weitere Klasse "Vollfederrahmen" erstellen, die von "Rahmen" erbt. "Vollfederrahmen" hat dann alles, was "Rahmen" auch kann/hat (z.B. "Rohstoff" und "Farbe"), plus die für den "Vollfederrahmen" (z.B. "FederArt") spezifischen Attribute. Die anderen "Rahmen"-Objekte bleiben in ihrer Struktur jedoch bestehen und du hast keinen bestehenden Code angefasst und damit Veränderungen im Ablauf verursacht.

Dadurch bist du im Klassen-Modell sehr flexibel und kannst damit neue Fahrräder zusammen stellen in dem du nur eine Komponente austauschst.

Vielleicht wird die Vererbung jetzt etwas deutlicher.

Wenn du deiner User-Klasse nur User-spezifische Attribute und Methoden gibst, hast du ein loses Modell, das du an vielen anderen Stellen einsetzen kannst.

Aber sheel hat in sofern Recht, dass es sinnvoll ist, erstmal OOP an sich zu verstehen und anzuwenden. Das Thema ist sehr breit und es gibt dort noch viel zu erfahren ;-)
 
ok ihr seid euch einig, das finde ich immer gut und werde ich auch zu herzen nehmen wenn gleich ich denke es hat klick gemacht.

Ich Könnte zB eine Klasse lebenauf dem Planeten erstellen, dort packe ich rein, säugetiere.

alle säugetiere haben gemeinsame eigenschaften function Sauerstoffverbrauch.

Möchte ich nun zwischen mensch und tier unterscheiden erstelle ich jeweils eine klasse die die grundeigenschaften der Hauptklasse annimmt und wo ich dann unterscheiden kann zwischen den verschiedenen tierarten im einenn und in der anderen klasse zB nach verschiedenen nationalitäten.
 
Zurück