Portal > Foren > PHP > PHP-Programmierung > Problem mit Vererbung (PHP)
Antwort
 
Themen-Optionen
Alt 12.09.2006, 15:37 Nach oben    #1
Neuer Benutzer
 
Registriert seit: 12.09.2006
Beiträge: 12
Standard Problem mit Vererbung (PHP)

Hallo Leute,

ich habe ein kleines Problem: Ich habe 3 Klassen, wobei Klasse B und C von Klasse A abgeleitet sind. Nun möchte ich beim Erzeugen eines Objektes der Klasse C in der Klasse A spezifische Änderungen durchführen lassen (ebenso, wenn ich ein Objekt nach Klasse B erzeuge), die von der aufrufenden Klasse abhängig sind. Gibt es eine Möglichkeit, die aufrufende Klasse zu ermitteln?

Mfg, kari01
kari01 ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 15:49 Nach oben    #2
Martin Breuer
 
Benutzerbild von WarrenFaith
 
Registriert seit: 17.08.2005
Ort: Berlin
Beiträge: 1.642
Standard

Da alles was in A ist, auch in B/C ist, brauchst du nichts bei A ändern, denn A ist einfach ein Teil des Objekts von B bzw C (je nachdem).

Was genau willst du denn ändern? Weil ehrlich gesagt glaube ich, dass dir die Vererbung noch nicht zu 100% ins Blut übergegangen ist.
Verfeinere bitte deine Frage mit einem Beispiel und ich kann meine Antwort verfeinern.
__________________
I did it my way - Senseless-Blog
WarrenFaith ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 15:50 Nach oben    #3
Ben
Benjamin Klaile
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.471
Standard

Jetzt ohne große über Vor-/Nachteile nachgedacht zu haben ..

PHP-Code:
class {
    public function 
__construct($subclass) {
         switch(
$subclass) {
               case 
'B'// mach was
                   
break;

               case 
'C'// mach was
                   
break;

               default: 
// mach was
         
}
    }
}


class 
extends {
    public function 
__construct() {
        
parent::__construct(__CLASS__);
    }
}

class 
extends {
    public function 
__construct() {
        
parent::__construct(__CLASS__);
    }

Sowas?


[Nachtrag]
Sehe zwar gerade nicht den Sinn und Zweck, aber nunja ...

Geändert von Ben (12.09.2006 um 15:51 Uhr). Grund: Nachtrag hinzugefügt
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 15:57 Nach oben    #4
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 826
Standard

get_class($this) wäre da einfacher...

Basti
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 16:07 Nach oben    #5
Ben
Benjamin Klaile
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.471
Standard

Ah, gibt es ja auch ein Beispiel im Manual zu, auch wenn dieses ein wenig inkorrekt ist. Aber das Prinzip kann man ja erkennen.
http://de2.php.net/manual/en/functio...lass.php#65249
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 16:09 Nach oben    #6
Martin Breuer
 
Benutzerbild von WarrenFaith
 
Registriert seit: 17.08.2005
Ort: Berlin
Beiträge: 1.642
Standard

Ich versuche noch den Sinn zu verstehen... *help*
__________________
I did it my way - Senseless-Blog
WarrenFaith ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 16:16 Nach oben    #7
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 826
Standard

Ich hab zum Besipiel eine abstrakte View-Klasse mit einer Methode display(). Diese kann überschrieben werden, lässt aber, wenn sie eben nicht überschrieben wird, ein Template parsen und ausspucken. Der Name des Templates wird automatisch aus dem Namen der View-Klasse abgeleitet. Folglich muss die abstrakte View-Klasse ja "wissen", von welcher Klasse das Objekt ist, das da von ihr abgeleitet wird.

Basti
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 16:20 Nach oben    #8
Martin Breuer
 
Benutzerbild von WarrenFaith
 
Registriert seit: 17.08.2005
Ort: Berlin
Beiträge: 1.642
Standard

Hm... ich hätte das mit ner Klassenvariable und nem Konstruktor gelöst...
__________________
I did it my way - Senseless-Blog
WarrenFaith ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 16:35 Nach oben    #9
Neuer Benutzer
 
Registriert seit: 12.09.2006
Beiträge: 12
Standard

Ok, ich versuch es zu verdeutlichen.

Klasse A ist eine Allgemeine Benutzerklasse, sie enthält Funktionen zum Löschen, Ausgeben von allgemeinenen Benutzerinfos und sonstigen Krimskrams. Jedoch sind einige Funktionen teilweise abhängig davon, wer die Kindklasse ist - ausgabe von Benutzerinformationen ist zum Beispiel so angelegt, dass die Queries, die erzeugt werden, jeweils auf die Subklasse zugeschnitten sind (da die Daten in unterschiedlichen Tabellen liegen), das Prinzip jedoch bei allen gleich.

Klasse B/C (extends Klasse A), sind spezielle Benutzer, die nur noch ihre Besonderheiten enthalten, zum Beispiel abweichende updates und inserts.

Im Moment muss ich noch beim Objekterzeugen klarmachen, welche Kindklasse Klasse A aufruft. Jedoch soll Klasse A optimalerweise selber herausfinden, von welcher Klasse sie erweitert wurde.

Geändert von kari01 (12.09.2006 um 16:37 Uhr). Grund: kleinere erweiterung
kari01 ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 16:35 Nach oben    #10
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 826
Standard

Zitat:
Zitat von WarrenFaith Beitrag anzeigen
Hm... ich hätte das mit ner Klassenvariable und nem Konstruktor gelöst...
DRY!


Basti
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 16:50 Nach oben    #11
Martin Breuer
 
Benutzerbild von WarrenFaith
 
Registriert seit: 17.08.2005
Ort: Berlin
Beiträge: 1.642
Standard

was auch immer dein "DRY!" heißen soll.
Normalerweise sollen doch nur Gemeinsamkeiten in der "Vaterklasse" sein, demzufolge wiederspricht es doch der Logik von Vererbung, wenn in der Vaterklasse funktionen sind, die je nach Kindklasse anders arbeiten sollen.
Da wäre es sinnvoller, in den Kindklassen die Funktionen zu überladen...
__________________
I did it my way - Senseless-Blog
WarrenFaith ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 16:56 Nach oben    #12
Neuer Benutzer
 
Registriert seit: 12.09.2006
Beiträge: 12
Standard

Ansich sind es ja wirklich nur die Queries die minimaler Anpassung bedürfen und ich war daher der Ansicht, dass sich die Elternklasse etwas flexibel zeigen könnte ^^.

Völlig falscher Ansatz?

[PS] DRY - Don't repeat yourself

Geändert von kari01 (12.09.2006 um 16:56 Uhr). Grund: PS hinzugefügt
kari01 ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 17:02 Nach oben    #13
Martin Breuer
 
Benutzerbild von WarrenFaith
 
Registriert seit: 17.08.2005
Ort: Berlin
Beiträge: 1.642
Standard

Danke für die Erklärung.
Zum Glück habe ich mich ja nicht wiederholt.

Back to topic:
Wenns nur kleine Änderungen sind, ists aus Gründen der Bequemlichkeit sicherlich verständlich und es ist nichts dagegen zu sagen.
Allerdings wiederspricht es doch eher meiner Logik der Vererbung. Aber vielleicht sehe ich das auch etwas zu verbissen.
__________________
I did it my way - Senseless-Blog
WarrenFaith ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 17:03 Nach oben    #14
Johannes Schlichenmaier
 
Benutzerbild von Jojo
 
Registriert seit: 26.08.2005
Ort: Mannheim
Beiträge: 395
Standard

Nimm WarrenFaith' Vorschlag und überlade die Konstruktoren.
Du kannst ja alles gemeinsame in eine Methode in die Elternklasse packen, wenn du willst.

Is sicherlich sauberer ...
__________________
In the beginning was the word
and the word was content-type: plain/text

heute code ich, morgen debug ich und uebermorgen cast ich die koenigin auf int
Jojo ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 17:29 Nach oben    #15
Neuer Benutzer
 
Registriert seit: 12.09.2006
Beiträge: 12
Standard

Um meine momentane Lösung mal zu zeigen... Nur halt wäre es mir lieber, wenn user von selbst drauf kommt, dass club ihn extended hat ^^

PHP-Code:
<?php
class club extends user
{    
    private function 
__construct()
    {
        
    }
    
    public function 
get_instance()
    {
        
parent::get_instance('cl');
    }

    public function 
__destruct()
    {
        
parent::__destruct();
    }

    public function 
insert($data)
    {
        if (!empty(
$data))
        {
            
$user_id parent::insert($data);
            
$sqlclub "INSERT INTO
                        club
                        SET
                         user_id = "
.$user_id.",
                         telephone ='"
.$data['telephone']."',
                         website = '"
.$data['website']."',
                         [...]
                         lastupdate=NOW()"
;
            
db::insert($sqlclub);
            return 
true;
        }
        else
        {
            return 
false;
        }
    }
}
?>
PHP-Code:
<?php
class user
{    
    private static 
$instance     NULL;
    private static 
$type         NULL;
    private static 
$typetable    NULL;
    private static 
$typefull    NULL;
    private static 
$smarty         NULL;
    

    private function 
__construct($tp=NULL)
    {
        switch(
$tp)
        {
            case 
"cl" 
                
self::$type $tp;
                
self::$typetable "club";
                
self::$typefull  "club";
            break;
            case 
"nn" :
                
self::$type $tp;
                
self::$typetable "normal";
                
self::$typefull  "normal";
            break;
        }
    }
    
    public function 
get_instance($tp=NULL)
    {
        if(
self::$instance == NULL)
            
self::$instance = new user($tp);
    }

    public function 
__destruct()
    {
        
self::get_instance(self::$type);
        
self::$instance NULL;
    }

    public function 
tempMethod()
    {
        
self::get_instance(self::$type);
    }
    
    public function 
setSmarty(&$smarty)
    {
        
self::get_instance(self::$type);
        
self::$smarty $smarty;
    }
     
    public function 
getAll()
    {
        if(
array_key_exists('next'$_REQUEST) && is_numeric($_REQUEST['next']) && $_REQUEST['next'] > 0)
            
$next $_REQUEST['next'];
        else
            
$next 1;
        
        
self::$smarty->assign('next',$next-1);
        
        
$sql "SELECT
                     count(user_id) as count 
                FROM
                     "
.self::$typetable;
                     
        
$count db::select_one($sql);
        
$count $count['count'];
        
        
$items_per_page 50;
        
        
SmartyPaginate::connect();
        
SmartyPaginate::setLimit($items_per_page);
        
SmartyPaginate::setTotal($count);
        
SmartyPaginate::setUrl(self::$typefull.'_all.php');
        
SmartyPaginate::assign(self::$smarty);
        
        if(
array_key_exists('oder'$_REQUEST) && !empty($_REQUEST['order']))
            
$order $_REQUEST['order'];
        else
            
$order "user.name";
            
        if(
array_key_exists('sort'$_REQUEST) && !empty($_REQUEST['sort']))
            
$sort $_REQUEST['sort'];
        else
            
$sort "asc";
            
        
$sql "select 
                    user.name, 
                    user.user_id, 
                    user.country, 
                    user.city, 
                    user.postcode, 
                    user.street,
                    user.streetnumber
                from
                    "
.self::$typetable.",
                    user
                where 
                    user.user_id = "
.self::$typetable.".user_id 
                order by 
                    "
.$order." ".$sort.
                limit 
                    "
.($next-1).", ".$items_per_page;
        
        
$tmp db::select($sql);
        
        return 
$tmp;
    }
    
    public function 
getDetails($id)
    {
        
$sql "SELECT 
                    * 
                FROM 
                    "
.self::$typetable.", 
                    user 
                WHERE 
                    "
.self::$typetable.".user_id = user.user_id 
                    AND "
.self::$typetable.".user_id =".$id;
        
$data db::select_one($sql);
        return 
$data;
    }
    
    public function 
insert($data)
    {
        if(!empty(
$data))
        {
            
$sqluser "INSERT INTO
                        user
                        SET
                         name = '"
.$data['name']."',
                         pass = MD5('"
.$data['pass']."'),
                         [...]
                         isfrontend = "
.$data['isfrontend'].",
                         isbackend  = "
.$data['isbackend'].",
                         isenabled  = 1"
;
            
$id db::insert($sqluser);    
            
debug::show_var($sqluser);
            
filesystem::mk_dir(PATH."content/".$id."/");
            if (!empty(
$id))
            {
                return 
$id;
            }
            else
            {
                return 
false;
            }
        }
        else
        {
            return 
false;
        }
    }
        
    public function 
delete($id)
    {
       
// Delete halt     
        
    
}
    
}
?>

Geändert von kari01 (12.09.2006 um 17:31 Uhr). Grund: kleiner fehler
kari01 ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 17:43 Nach oben    #16
Martin Breuer
 
Benutzerbild von WarrenFaith
 
Registriert seit: 17.08.2005
Ort: Berlin
Beiträge: 1.642
Standard

PHP-Code:
<?php
class club extends user
{    
    private function 
__construct()
    {
        
self::$type $tp;
        
self::$typetable "club";
        
self::$typefull  "club";
    }
    
// aufs wichtigste gekürzt
}
?>
PHP-Code:
<?php
class user
{    
    private static 
$instance     NULL;
    private static 
$type         NULL;
    private static 
$typetable    NULL;
    private static 
$typefull    NULL;
    private static 
$smarty         NULL;
    

    private function 
__construct()
    {
        
    }
    
//aufs wichtigste gekürzt
    
}
?>
und das gleiche machste mit der anderen klasse, die von user erbt.
Ich versteh aber noch nicht so ganz warum deine Klassenvariablen alle static sind. Aber gut, du wirst schon wissen warum (hab sicherlich wieder was übersehen).
__________________
I did it my way - Senseless-Blog
WarrenFaith ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 19:00 Nach oben    #17
Neuer Benutzer
 
Registriert seit: 12.09.2006
Beiträge: 12
Standard

Super, danke! Ich probier das dann gleich mal aus.

Kleine Frage noch: Ist das schon stark an einer sauberen OOP vorbei oder ist das so iO?
kari01 ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 21:22 Nach oben    #18
Martin Breuer
 
Benutzerbild von WarrenFaith
 
Registriert seit: 17.08.2005
Ort: Berlin
Beiträge: 1.642
Standard

also man kanns übertreiben, von daher denke ich, dass es so definitiv ok ist. ansonsten ist jeder weg der geht sauber *duck und renn*
__________________
I did it my way - Senseless-Blog
WarrenFaith ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.09.2006, 22:41 Nach oben    #19
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 826
Standard

Zitat:
Zitat von kari01 Beitrag anzeigen
Kleine Frage noch: Ist das schon stark an einer sauberen OOP vorbei oder ist das so iO?
Hi.

Wichtig ist einfach, dass du das Gemeinsame in die User-Klasse auslagerst (Generalisierung ist hier vielleicht der klarere Ausdruck, als Vererbung). Das kann genausogut eine Methode sein, die immer das gleiche tut (hier kannst du durch Parameter aus der speziellen Klasse auf die Methode der generellen Klasse "einwirken"), als auch eine, die sich auf den Zustand des Objektes bezieht (diesen kannst du vorher entsprechend verändern).

Natürlich kannst du eine Methode auch überschreiben - entweder "komplett", wenn das spezielle Verhalten vom generellen komplett abweicht oder, indem die Methode quasi dekoriert wird, also vielleicht zuerst eine Operation durchgeführt wird und dann die Methode der Basisklasse aufgerufen wird.

Und genau das tust du ja (bzw. umgekehrt), allerdings nicht konsequent.

Die Prüfung, ob es Daten ($data) gibt machst du z.B. doppelt. Das ist unnötig. Auch nicht sauber ist, dass die Methode plötzlich nichtmehr die ID sondern true zurückgibt, wenn es klappt. Besser:
PHP-Code:
public function insert($data)
    {
        
$user_id parent::insert($data);

        if (!
$user_id)
            return 
false;

        
$sqlclub "INSERT INTO
                        club
                    SET
                        user_id = "
.$user_id.",
                        telephone ='"
.$data['telephone']."',
                        website = '"
.$data['website']."',
                        [...]
                        lastupdate=NOW()"
;
        
db::insert($sqlclub);

  &