PHP, Wann :: und wann -> benutzen?

hazzilein

Lieutenant
Registriert
Mai 2008
Beiträge
692
Hallo,
leider finde ich über google nichts hilfreiches zu meiner Frage.

Wann benutze ich in PHP :: und wann ->
Also wie kann ich mir das in meinen Modell das ich im Kopf habe einprägen? Was bedeutet es?

Wenn ich ein Array erstelle sage ich ja => und nicht -> also damit hat das scheinbar nichts zutun. Hier ein Beispiel.

Wäre nett wenn mir kurz jemand auf die Sprünge helfen könnte :)


Code:
  // Konstruktor
  public function __construct($id,$n,$a,$g=NULL,$h=NULL,$c=NULL,$u){

  //Konstruktor Person aufrufen

  // Person parent von Freund
  parent::__construct($n);
  self::$zaehler++; // variable oben, self bezeichnet klasse
  //$this -> name = $n;
  $this -> id1 = $id;
  $this -> alter = $a;
  $this -> groesse = $g;
  $this -> haarfarbe = $h;
  $this -> cool = $c;
  $this -> url = $u;
  }
  
  
  public function alsCSVZeile(){
  return 
         
         $this -> id1 . ";" .
         $this -> name . ";" .
         $this -> alter . ";" . 
         $this -> groesse . ";" . 
         $this -> haarfarbe . ";" .
         $this -> cool . ";" .
         $this -> url;  // beendet return
  }
 
bin zwa mehr C bewandert sollte hier aber das selbe sein:
"->" bei Pointern. this ist ein Pointer zum Objekt in dem die methode aufgerufen wird. Also falls du eine funktion oder eine variable eines Objektes aufrufen willst zu dem du den Pointer hast musst du "->" verwenden.
"::" ist der Scope operator (Sichtbarkeit). self::$zaehler++ sagt also das die variable "zaehler" der klasse self erhöht werden soll
 
Ok ich glaub das muss ich jetz öfter lesen damit ich es verstehe ;)
 
@Narkry: Leider nicht ganz richtig - in PHP gibt es z.B. keine Zeiger.

@hazzilein: Mit '->' greifst du auf die Member einer Instanzvariable zu. Aber mit '::' greifst du in den meisten Fällen auf statische Funktionen eines Objektes direkt zu, ohne das du dieses Objekt instanzieren musst. ;)
 
im großen und ganzen kann man sich merken, dass -> bei objekten genutzt wird und :: bei statisch markierten variablen und funktionen. was anderes einfacheres/besseres fällt mir dazu jetz nich ein.

vllt mal paar beispiele:
PHP:
<?php

class test
{
  static protected $AnzahlKlassen = 0;
  static public $TestWert = 24;
  
  static protected $Assignments = 0;
  protected $test;
  
  public function __construct( $test )
  {
    ++self::$AnzahlKlassen;
    $this->setTest( $test );
  }
  
  public function __destruct()
  {
    --self::$AnzahlKlassen;
  }
  
  public function getTest() { return $this->test; }
  public function setTest( $test ) { ++self::$Assignments; $this->test = $test; }
  
  public function getAnzahlKlassen() { return self::$AnzahlKlassen; }
}

class test_new extends test
{
  protected $test_new;
  
  public function __construct( $test, $test_new )
  {
    parent::__construct( $test );
    $this->setTest_new( $test_new );
  }
  
  public function getTest_new() { return $this->test_new; }
  public function setTest_new( $test_new ) { $this->test_new; }
}

$a = new test( 1 );
$a->setTest( 5 );
echo test::$TestWert.'<br>';
echo $a->getTest().'<br>';
test::$TestWert = 10;
echo test::$TestWert.'<br>';
echo $a->getAnzahlKlassen().'<br>';

?>
@ Narkry: self bezeichnet die eigene klasse, in welcher man sich gerade befindet. vermisst man bei cpp leider. :( parent beschreibt die oberklasse (= super in java, wenn ich mich recht entsinne).
 
claW's Beispiel ist zwar etwas umfangreicher, aber ich habe mir gerade auch die Arbeit gemacht und denke mal, dass ich dann trotzdem mal mein Beispiel posten darf.

PHP:
<?php

    class MeineKlasse {

        public function __construct() {
            echo "Es wurde ein neues Objekt der Klasse 'MeineKlasse' erzeugt! <br>";
        }

        //Diese Methode kann auch ohne Instanzierung aufgerufen werden, da sie statisch ist
        public static function printStatic() {
            echo "Die Methode 'printStatic' der Klasse 'MeineKlasse' wurde aufgerufen <br>";
        }

        //Diese Methode kann erst nach Instanzierung aufgerufen werden
        public function printHelloWorld() {
            echo "HelloWorld <br>";
        }
    }

    MeineKlasse::printStatic();

    $C = new MeineKlasse();
    $C->printHelloWorld();

?>
 
Danke für die Mühe ich glaube langsam verstehe ich es, bin noch Anfänger :)

Instanzierung bedeutet im Beispiel von Twaddler, dass ich quasi ein Objekt $C der Klasse "MeineKlasse" erstelle, und danach kann ich erst auf die Funktionen der Klasse zugreifen, also die printHelloWorld Funktion.

Auf die statische kann ich immer zugreifen, ohne dass ich ein Ob jekt der Klasse MeineKlasse erstelle, seh ich das richtig?
 
Alles klar, dankeschön. Und was bringt mir das ganze? Ich meine wieso mache ich nicht alles static :D
 
Befass dich ein wenig mit Objektorientierung, dann verstehst du warum ;)

Kurzes Beispiel: du hast eine Klasse mit non-static Variablen drin, legst davon mehrere Instanzen an; jede Instanz hat ihre eigenen Variablen(werte). Machst du die Variablen static, haben alle Instanzen dieselben Variablen und Werte. Mit static-Methoden kannst du nicht auf non-static Variablen zugreifen.

Kann nur von Java sprechen in dem Punkt:
Code:
class Test { // klasse Test
  private static int allCount = 0; // statische Variable
  private int ownCount; // nichtstatische Variable

  public Test() { // Konstruktor
    ownCount = 0; // nichtstatische Variable auf 0 setzen
  }

  public static void incAllCount() { // Methode um statische Variable zu erhoehen
    allCount++;
  }

  public void incOwnCount() { // Methode um nichtstatische Variable zu erhoehen
    ownCount++;
  }

  public static void retAllCount() { // Methode um statische Variable zurueckzugeben
    return allCount;
  }

  public void retOwnCount() { // Methode um nichtstatische Variable zurueckzugeben
    return ownCount;
  }

  public static void main(String[] args) { // Hauptmethode des Programms
    Test testEins = new Test(); // neue Instanz (Objekt) testEins der Klasse Test
    Test testZwei = new Test(); // neue Instanz (Objekt) testZwei der Klasse Test
    testEins.incOwnCount(); // erhoehe die eigene Variable
    testZwei.incAllCount(); // erhoehe die statische Variable
    testEins.incAllCount(); // erhoehe die statische Variable
    System.out.println(testEins.retOwnCount()); // gibt 1, Rueckgabe der eigenen Variable des Objektes testEins
    System.out.println(testEins.retAllCount()); // gibt 2, Rueckgabe der statischen Variable der Klasse Test (nicht des Objektes testEins!)
    System.out.println(testZwei.retOwnCount()); // gibt 0, Rueckgabe der eigenen Variable des Objektes testZwei
    System.out.println(testZwei.retAllCount()); // gibt 2, Rueckgabe der statischen Variable der Klasse Test (nicht des Objektes testZwei!)
    System.out.println(Test.retAllCount()); // gibt 2, Rueckgabe der statischen Variable der Klasse Test
  }
}

incOwnCount() und retOwnCount() koennen nur von einem instanziierten Objekt der Klasse Test zurueckgegeben werden.
 
Zuletzt bearbeitet:
hazzilein schrieb:
Und was bringt mir das ganze? Ich meine wieso mache ich nicht alles static :D
wenn du alles als statisch deklarierst, bekommst du irgendwann probleme mit objekten. wie viel weißt du denn schon bzgl. static bzw. objektorientierung? ich beschreib lieber mal nur static, alles sonst findest du zuhauf in tutorials oder ggf. fragst du nochmal im forum nach.

static deklariert methoden oder variablen als statisch, d.h. dass diese ohne instanziiert zu werden, verwendet werden können. statische variablen gehören dann aber immer nur zu einer klasse, nicht statische allerdings zu einem objekt.
PHP:
<?php

class test { public $a; }
class test2 { static public $a; }

# non-static
$a = new test();
$a->a = 5;
echo $a->a.'<br>'; # ausgabe: 5

$b = new test();
$b->a = 6;
echo $b->a.'<br>'; # ausgabe: 6

echo $a->a.'<br>'; # ausgabe: 5

# static
$x = new test2();
$x::$a = 10;
echo $x::$a.'<br>'; # ausgabe: 10

$y = new test2();
$y::$a = 15;
echo $y::$a.'<br>'; # ausgabe: 15

echo $x::$a.'<br>'; # ausgabe: 15, obwohl $x::$a zuletzt auf 10 gesetzt wurde

# $x->a funktioniert nicht, da php hier eine variable $a zur laufzeit selbst hinzufügt. leider ein dummes verhalten, vllt kommt sowas ja bald mal weg...

?>
früher oder später (wenn du tiefer in die entwicklung gehst), brauchst du sowas z.b. für irgendwelche patterns - singleton ist eins davon. im prinzip erstellst du beim ersten aufruf eine instanz der klasse und kannst immer wieder, bei egal welchem aufruf, genau auf diese instanz zurückgreifen. z.b. is das sinnvoll für konfigurationen, userdaten, serverdaten, templates, datenbankverbindungen, ... du wirst schon dahinter steigen wenn du es brauchst. :) sinnvoll ist static auch, wenn du nicht erst ein objekt von einer klasse instanziieren willst, wenn du nur eine methode brauchst (diese darf aber nicht $this verwenden und auf keine instanzvariablen der klasse zugreifen!).

vllt mal ein beispiel aus c++ (schlüsselwörter sind fast identisch, aufbau fast genauso):
Code:
class Memory
{
  protected :
    static bool GetStructure( MEMORYSTATUSEX &Memory )
    {
      memset( &Memory, 0, sizeof( MEMORYSTATUSEX ) );
      Memory.dwLength = sizeof( MEMORYSTATUSEX );
      return GlobalMemoryStatusEx( &Memory ) != 0;
    }
  public :
    static uint8 PercentageLoad( void )
    {
      MEMORYSTATUSEX mem;
      return GetStructure( mem ) ?
        (uint8)mem.dwMemoryLoad :
      0l;
    }
    static uint64 AvailableRAM( void )
    {
      MEMORYSTATUSEX mem;
      return GetStructure( mem ) ?
        mem.ullAvailPhys :
      0l;
    }
    static uint64 TotalRAM( void )
    {
      MEMORYSTATUSEX mem;
      return GetStructure( mem ) ?
        mem.ullTotalPhys :
      0l;
    }
    static uint64 UsedRAM( void )
    {
      MEMORYSTATUSEX mem;
      return GetStructure( mem ) ?
        mem.ullTotalPhys - mem.ullAvailPhys :
      0;
    }
    static uint64 AvailablePageFile( void )
    {
      MEMORYSTATUSEX mem;
      return GetStructure( mem ) ?
        mem.ullAvailPageFile :
      0l;
    }
    static uint64 TotalPageFile( void )
    {
      MEMORYSTATUSEX mem;
      return GetStructure( mem ) ?
        mem.ullTotalPageFile :
      0l;
    }
    static uint64 UsedPageFile( void )
    {
      MEMORYSTATUSEX mem;
      return GetStructure( mem ) ?
        mem.ullTotalPageFile - mem.ullAvailPageFile :
      0l;
    }
    static uint64 AvailableVirtual( void )
    {
      MEMORYSTATUSEX mem;
      return GetStructure( mem ) ?
        mem.ullAvailVirtual :
        0l;
    }
    static uint64 TotalVirtual( void )
    {
      MEMORYSTATUSEX mem;
      return GetStructure( mem ) ?
        mem.ullTotalVirtual :
        0l;
    }
    static uint64 UsedVirtual( void )
    {
      MEMORYSTATUSEX mem;
      return GetStructure( mem ) ?
        mem.ullTotalVirtual - mem.ullAvailVirtual :
      0l;
    }
    static uint64 MaximumAvailableRAM( uint64cr MaximumSize )
    {
      MEMORYSTATUSEX mem;
      if( GetStructure( mem ) )
      {
        uint64 r = MaximumSize;
        if( MaximumSize > mem.ullAvailVirtual ) r = mem.ullAvailVirtual;
        if( mem.ullAvailPhys < mem.ullAvailVirtual && MaximumSize > mem.ullAvailPhys ) r = mem.ullAvailPhys;
        return r;
      }
      return 0l;
    }
};
bei dieser klasse wäre es z.b. blödsinnig, wenn du erst folgendes schreiben musst (mal amateurhaft auf php übertragen, denke damit kannst du es besser verstehen):
Code:
$a = new Memory();
$ram = $a->TotalRAM();
deswegen kann man die methoden als statisch deklarieren, damit man folgendes schreiben kann:
Code:
$ram = Memory::TotalRAM();
 
Zurück
Oben