Frage

Wenn ich mehrere Klassen mit Funktionen habe, die ich brauche, aber separat für die Organisation speichern möchte, kann ich eine Klasse für beide erweitern?

dh class a extends b extends c

Bearbeiten: Ich weiß, wie man die Klassen nach dem anderen verlängert, aber ich suche nach einer Methode, um eine Klasse sofort mit mehreren Basisklassen zu erweitern - AFAIK, Sie können dies nicht in PHP tun, aber es sollte Wege umgehen, ohne auf zurückzugreifen class c extends b, class b extends a

War es hilfreich?

Lösung

Beantwortung Ihrer Bearbeitung:

Wenn Sie wirklich mehrere Vererbung fälschen möchten, können Sie die magische Funktion __call () verwenden.

Dies ist hässlich, obwohl es aus Sicht eines Benutzers der Klasse der Benutzer funktioniert:

class B {
    public function method_from_b($s) {
        echo $s;
    }
}

class C {
    public function method_from_c($s) {
        echo $s;
    }
}

class A extends B
{
  private $c;

  public function __construct()
  {
    $this->c = new C;
  }

  // fake "extends C" using magic function
  public function __call($method, $args)
  {
    $this->c->$method($args[0]);
  }
}


$a = new A;
$a->method_from_b("abc");
$a->method_from_c("def");

Druckt "abcdef"

Andere Tipps

Sie können keine Klasse haben, die zwei Basisklassen erweitert. Du könntest nicht haben.

// this is NOT allowed (for all you google speeders)
Matron extends Nurse, HumanEntity

Sie könnten jedoch eine Hierarchie wie folgt haben ...

Matron extends Nurse    
Consultant extends Doctor

Nurse extends HumanEntity
Doctor extends HumanEntity

HumanEntity extends DatabaseTable
DatabaseTable extends AbstractTable

usw.

Sie könnten Merkmale verwenden, die hoffentlich bei PHP 5.4 erhältlich sein werden.

Merkmale sind ein Mechanismus für die Wiederverwendung von Code in einzelnen Vererbungssprachen wie PHP. Ein Merkmal soll einige Einschränkungen der einzelnen Vererbung verringern, indem ein Entwickler in mehreren unabhängigen Klassen, die in verschiedenen Klassenhierarchien leben, frei wiederverwenden können. Die Semantik der Kombination von Merkmalen und Klassen wird in gewisser Weise definiert, was die Komplexität verringert und die typischen Probleme vermeidet, die mit mehreren Vererbung und Mischung verbunden sind.

Sie sind für ihr Potenzial anerkannt, um eine bessere Zusammensetzung und Wiederverwendung zu unterstützen, daher ihre Integration in neuere Versionen von Sprachen wie Perl 6, Squeak, Scala, Slate und Festung. Merkmale wurden auch auf Java und C#portiert.

Mehr Informationen: https://wiki.php.net/rfc/traits

Klassen sollen nicht nur Methodensammlungen sein. Eine Klasse soll ein abstraktes Konzept darstellen, wobei sowohl der Zustand (Felder) als auch das Verhalten (Methoden), das den Zustand verändert. Die Verwendung von Vererbung, nur um ein gewünschtes Verhalten zu erhalten Eine Klasse, die 100 Methoden und 20 Felder erbt, aber immer nur 5 von ihnen verwendet.

Ich glaube, es gibt Pläne, bald Mix-Ins hinzuzufügen.

Aber bis dahin gehen Sie mit der akzeptierten Antwort. Sie können das ein wenig abstrahieren, um eine "erweiterbare" Klasse zu erstellen:

class Extendable{
  private $extender=array();

  public function addExtender(Extender $obj){
    $this->extenders[] = $obj;
    $obj->setExtendee($this);
  }

  public function __call($name, $params){
    foreach($this->extenders as $extender){
       //do reflection to see if extender has this method with this argument count
       if (method_exists($extender, $name)){
          return call_user_func_array(array($extender, $name), $params);
       }
    }
  }
}


$foo = new Extendable();
$foo->addExtender(new OtherClass());
$foo->other_class_method();

Beachten Sie, dass in diesem Modell "otherClass" über $ foo 'wissen'. AndereClass muss eine öffentliche Funktion namens "Setextendee" haben, um diese Beziehung aufzubauen. Wenn dann Methoden von $ foo aufgerufen werden, kann es intern auf $ foo zugreifen. Es wird jedoch keinen Zugriff auf private/geschützte Methoden/Variablen wie eine echte erweiterte Klasse erhalten.

Die derzeit akzeptierte Antwort von @Frank wird funktionieren, aber es ist nicht mehrfach die Erbe, sondern eine untergeordnete Unterrichtsinstanz der Klassen, die aus Geltungsbereich definiert ist. Auch gibt es die __call() Kurzschrift - Überlegen Sie, nur zu verwenden $this->childInstance->method(args) Überall, wo Sie eine externe Klassenklassenmethode in der "erweiterten" Klasse benötigen.

Genaue Antwort

Nein, du kannst jeweils nicht wirklich, als Handbuch von extends Stichwort sagt:

Eine erweiterte Klasse hängt immer von einer einzelnen Basisklasse ab, dh mehrerer Vererbung wird nicht unterstützt.

Echte Antwort

Wie @Adam korrekt vorgeschlagen hat, verbietet dies Sie jedoch nicht, mehrere hierarchische Vererbung zu verwenden.

Sie können eine Klasse mit einer anderen und einer anderen mit einer anderen und so weiter erweitern ...

So ziemlich einfaches Beispiel dafür wäre:

class firstInheritance{}
class secondInheritance extends firstInheritance{}
class someFinalClass extends secondInheritance{}
//...and so on...

Wichtiger Hinweis

Wie Sie vielleicht bemerkt haben, Sie können nur mehrere (2+) Zwerge nach Hierarchie durchführen, wenn Sie die Kontrolle über alle im Prozess enthaltenen Klassen haben - Das heißt, Sie können diese Lösung nicht mit integrierten Klassen oder mit Klassen anwenden, die Sie einfach nicht bearbeiten können. Wenn Sie dies tun möchten, bleiben Sie bei der @Frank -Lösung - untergeordnete Instanzen.

... und endlich Beispiel mit etwas Ausgabe:

class A{
  function a_hi(){
    echo "I am a of A".PHP_EOL."<br>".PHP_EOL;  
  }
}

class B extends A{
  function b_hi(){
    echo "I am b of B".PHP_EOL."<br>".PHP_EOL;  
  }
}

class C extends B{
  function c_hi(){
    echo "I am c of C".PHP_EOL."<br>".PHP_EOL;  
  }
}

$myTestInstance = new C();

$myTestInstance->a_hi();
$myTestInstance->b_hi();
$myTestInstance->c_hi();

Welche Ausgänge

I am a of A 
I am b of B 
I am c of C 

Verwenden Sie Merkmale als Basisklassen. Verwenden Sie sie dann in einer übergeordneten Klasse. Erweitere es .

trait business{
  function sell(){

  }

  function buy(){

  }

  function collectMoney(){
  }

}

trait human{

   function think(){

   }

   function speak(){

   }

}

class BusinessPerson{
  use business;
  use human;
  // If you have more traits bring more
}


class BusinessWoman extends BusinessPerson{

   function getPregnant(){

   }

}


$bw = new BusinessWoman();
$bw ->speak();
$bw->getPregnant();

Siehe jetzt die Geschäftsfrau logisch erbte logisch geschäftlich und human beides;

<?php
// what if we want to extend more than one class?

abstract class ExtensionBridge
{
    // array containing all the extended classes
    private $_exts = array();
    public $_this;

    function __construct() {$_this = $this;}

    public function addExt($object)
    {
        $this->_exts[]=$object;
    }

    public function __get($varname)
    {
        foreach($this->_exts as $ext)
        {
            if(property_exists($ext,$varname))
            return $ext->$varname;
        }
    }

    public function __call($method,$args)
    {
        foreach($this->_exts as $ext)
        {
            if(method_exists($ext,$method))
            return call_user_method_array($method,$ext,$args);
        }
        throw new Exception("This Method {$method} doesn't exists");
    }


}

class Ext1
{
    private $name="";
    private $id="";
    public function setID($id){$this->id = $id;}
    public function setName($name){$this->name = $name;}
    public function getID(){return $this->id;}
    public function getName(){return $this->name;}
}

class Ext2
{
    private $address="";
    private $country="";
    public function setAddress($address){$this->address = $address;}
    public function setCountry($country){$this->country = $country;}
    public function getAddress(){return $this->address;}
    public function getCountry(){return $this->country;}
}

class Extender extends ExtensionBridge
{
    function __construct()
    {
        parent::addExt(new Ext1());
        parent::addExt(new Ext2());
    }

    public function __toString()
    {
        return $this->getName().', from: '.$this->getCountry();
    }
}

$o = new Extender();
$o->setName("Mahdi");
$o->setCountry("Al-Ahwaz");
echo $o;
?>

Ich habe mehrere Artikel gelesen, die die Vererbung in Projekten (im Gegensatz zu Bibliotheken/Frameworks) entmutigen und ermutigen, AGAISNT -Schnittstellen nicht gegen Implementierungen zu programmieren.
Sie befürworten auch für die Komposition: Wenn Sie die Funktionen in der Klasse A und B benötigen, machen C C mit Mitgliedern/Feldern dieses Typs:

class C
{
    private $a, $b;

    public function __construct($x, $y)
    {
        $this->a = new A(42, $x);
        $this->b = new B($y);
    }

    protected function DoSomething()
    {
        $this->a->Act();
        $this->b->Do();
    }
}

Multiple Vererbung scheint auf Schnittstellenebene zu funktionieren. Ich habe einen Test auf PHP 5.6.1 gemacht.

Hier ist ein Arbeitscode:

<?php


interface Animal
{
    public function sayHello();
}


interface HairyThing
{
    public function plush();
}

interface Dog extends Animal, HairyThing
{
    public function bark();
}


class Puppy implements Dog
{
    public function bark()
    {
        echo "ouaf";
    }

    public function sayHello()
    {
        echo "hello";
    }

    public function plush()
    {
        echo "plush";
    }


}


echo PHP_VERSION; // 5.6.1
$o = new Puppy();
$o->bark();
$o->plush();
$o->sayHello(); // displays: 5.6.16ouafplushhello

Ich dachte nicht, dass das möglich war, aber ich bin im Swiftmailer -Quellcode in der Klasse SWIFT_TRANSPORT_IBUFER gestoßen, die die folgende Definition hat:

interface Swift_Transport_IoBuffer extends Swift_InputByteStream, Swift_OutputByteStream

Ich habe noch nicht damit gespielt, aber ich dachte, es könnte interessant sein, es zu teilen.

Ich habe gerade mein "multiple Vererbung" -Problem gelöst mit:

class Session {
    public $username;
}

class MyServiceResponsetype {
    protected $only_avaliable_in_response;
}

class SessionResponse extends MyServiceResponsetype {
    /** has shared $only_avaliable_in_response */

    public $session;

    public function __construct(Session $session) {
      $this->session = $session;
    }

}

Auf diese Weise habe ich die Befugnis, die Sitzung in einer Sitzung zu manipulieren, die MyServicereSponsetype erweitert, die immer noch in der Lage ist, die Sitzung selbst zu bewältigen.

Sie können dies mit Merkmalen in PHP tun, die ab PHP 5.4 angekündigt wurden

Hier ist ein kurzes Tutorial für Sie, http://culttt.com/2014/06/25/php-traits/

PHP unterstützt noch nicht mehrfach die Vererbung der Klasse, sondern unterstützt jedoch die Vererbung der mehreren Schnittstellen.

Sehen http://www.hudzilla.org/php/6_17_0.php für einige Beispiele.

PHP erlaubt keine Mehrfachvererbung, aber Sie können mit der Implementierung mehrerer Schnittstellen ausmachen. Wenn die Implementierung "schwer" ist, sorgen Sie dafür Skelettimplementierung Für jede Schnittstelle in einer separaten Klasse. Dann kannst du Delegieren Sie alle Schnittstellenklassen an diese Skelettimplementierungen über Objektbehälter.

Wenn ich nicht genau weiß, was Sie erreichen möchten, würde ich empfehlen, die Möglichkeit zu untersuchen, Ihre Anwendung neu zu gestalten, um in diesem Fall eher die Komposition als die Vererbung zu verwenden.

Always good idea is to make parent class, with functions ... i.e. add this all functionality to parent.

And "move" all classes that use this hierarchically down. I need - rewrite functions, which are specific.

If you want to check if a function is public see this topic : https://stackoverflow.com/a/4160928/2226755

And use call_user_func_array(...) method for many or not arguments.

Like this :

class B {
    public function method_from_b($s) {
        echo $s;
    }
}

class C {
    public function method_from_c($l, $l1, $l2) {
        echo $l.$l1.$l2;
    }
}

class A extends B {
    private $c;

    public function __construct() {
        $this->c = new C;
    }

    public function __call($method, $args) {
        if (method_exists($this->c, $method)) {
            $reflection = new ReflectionMethod($this->c, $method);
            if (!$reflection->isPublic()) {
                throw new RuntimeException("Call to not public method ".get_class($this)."::$method()");
            }

            return call_user_func_array(array($this->c, $method), $args);
        } else {
            throw new RuntimeException("Call to undefined method ".get_class($this)."::$method()");
        }
    }
}


$a = new A;
$a->method_from_b("abc");
$a->method_from_c("d", "e", "f");

One of the problems of PHP as a programming language is the fact that you can only have single inheritance. This means a class can only inherit from one other class.

However, a lot of the time it would be beneficial to inherit from multiple classes. For example, it might be desirable to inherit methods from a couple of different classes in order to prevent code duplication.

This problem can lead to class that has a long family history of inheritance which often does not make sense.

In PHP 5.4 a new feature of the language was added known as Traits. A Trait is kind of like a Mixin in that it allows you to mix Trait classes into an existing class. This means you can reduce code duplication and get the benefits whilst avoiding the problems of multiple inheritance.

Traits

class A extends B {}

class B extends C {}

Then A has extended both B and C

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top