Heim > Artikel > Backend-Entwicklung > So implementieren Sie neue Merkmale der Code-Wiederverwendung in PHP
Ich bin beim Lesen des yii2-Quellcodes mit Merkmalen in Kontakt gekommen, also habe ich ihn studiert und einen Blog geschrieben, um ihn aufzuzeichnen.
Seit PHP 5.4.0 implementiert PHP eine Methode zur Code-Wiederverwendung namens Traits.
Traits ist ein Code-Wiederverwendungsmechanismus für Sprachen mit einfacher Vererbung wie PHP. Merkmale sollen die Einschränkungen von Sprachen mit einfacher Vererbung verringern und Entwicklern die freie Wiederverwendung von Methodensätzen in unabhängigen Klassen innerhalb verschiedener Hierarchien ermöglichen. Die Semantik von Merkmalen und die Klassenzusammensetzung definieren eine Möglichkeit, die Komplexität zu reduzieren und die typischen Probleme zu vermeiden, die mit traditioneller Mehrfachvererbung und Mixins verbunden sind.
Trait ähnelt einer Klasse, soll aber lediglich Funktionalität auf feinkörnige und konsistente Weise kombinieren. Ein Merkmal kann nicht allein instanziiert werden. Es fügt der herkömmlichen Vererbung eine Kombination horizontaler Funktionen hinzu, d. h. Mitglieder von Anwendungsklassen müssen nicht vererbt werden.
Merkmalsbeispiel
Der Code lautet wie folgt:
<?php trait ezcReflectionReturnInfo { function getReturnType() { /*1*/ } function getReturnDescription() { /*2*/ } } class ezcReflectionMethod extends ReflectionMethod { use ezcReflectionReturnInfo; /* ... */ } class ezcReflectionFunction extends ReflectionFunction { use ezcReflectionReturnInfo; /* ... */ } ?>
Priorität
Von der Basisklasse geerbte Mitglieder sind eingefügt durch Merkmal, das von Mitgliedern abgedeckt wird. Die Rangfolge besteht darin, dass Mitglieder der aktuellen Klasse die Methoden des Merkmals überschreiben und das Merkmal die geerbten Methoden überschreibt.
Beispiel für eine Prioritätsreihenfolge
Der Code lautet wie folgt:
<?php class Base { public function sayHello() { echo 'Hello '; } } trait SayWorld { public function sayHello() { parent::sayHello(); echo 'World!'; } } class MyHelloWorld extends Base { use SayWorld; } $o = new MyHelloWorld(); $o->sayHello(); ?>
Die obige Routine gibt Folgendes aus: Hallo Welt!
SayWorld, wo Mitglieder von der Basis geerbt haben Klasse werden eingefügt. Abgedeckt durch die sayHello-Methode in Trait. Sein Verhalten stimmt mit den in der MyHelloWorld-Klasse definierten Methoden überein. Die Rangfolge ist, dass Methoden in der aktuellen Klasse Merkmalsmethoden überschreiben, die wiederum Methoden in der Basisklasse überschreiben.
Ein weiteres Beispiel für eine Prioritätsreihenfolge
Der Code lautet wie folgt:
<?php trait HelloWorld { public function sayHello() { echo 'Hello World!'; } } class TheWorldIsNotEnough { use HelloWorld; public function sayHello() { echo 'Hello Universe!'; } } $o = new TheWorldIsNotEnough(); $o->sayHello(); ?>
Die obige Routine gibt Folgendes aus: Hallo Universum!
Mehrere Merkmale
werden durch Kommas getrennt. Mehrere Merkmale werden in der Verwendungsanweisung aufgeführt und können alle in eine Klasse eingefügt werden.
Beispiele für die Verwendung mehrerer Merkmale
Der Code lautet wie folgt:
<?php trait Hello { public function sayHello() { echo 'Hello '; } } trait World { public function sayWorld() { echo 'World'; } } class MyHelloWorld { use Hello, World; public function sayExclamationMark() { echo '!'; } } $o = new MyHelloWorld(); $o->sayHello(); $o->sayWorld(); $o->sayExclamationMark(); ?>
Die obige Routine gibt Folgendes aus: Hallo Welt!
Konflikt Auflösung
Wenn zwei Merkmale eine Methode mit demselben Namen einfügen, wird ein schwerwiegender Fehler generiert, wenn der Konflikt nicht explizit gelöst wird.
Um den Namenskonflikt mehrerer Merkmale in derselben Klasse zu lösen, müssen Sie den Statt-Operator verwenden, um explizit anzugeben, welche der widersprüchlichen Methoden verwendet werden sollen.
Mit der obigen Methode können nur andere Methoden ausgeschlossen werden. Der as-Operator kann eine der widersprüchlichen Methoden unter einem anderen Namen einführen.
Ein Beispiel für Konfliktlösung
Der Code lautet wie folgt:
<?php trait A { public function smallTalk() { echo 'a'; } public function bigTalk() { echo 'A'; } } trait B { public function smallTalk() { echo 'b'; } public function bigTalk() { echo 'B'; } } class Talker { use A, B { B::smallTalk insteadof A; A::bigTalk insteadof B; } } class Aliased_Talker { use A, B { B::smallTalk insteadof A; A::bigTalk insteadof B; B::bigTalk as talk; } } ?>
In diesem Fall verwendet Talker die Merkmale A und B. Da A und B widersprüchliche Methoden haben, definieren sie die Verwendung von smallTalk aus Merkmal B und bigTalk aus Merkmal A.
Aliased_Talker
verwendet den as-Operator, um talk als Alias von Bs bigTalk zu definieren.
Ändern Sie die Zugriffskontrolle der Methode
Die Verwendung der as-Syntax kann auch zum Anpassen der Zugriffskontrolle der Methode verwendet werden.
Ein Beispiel für die Änderung der Zugriffskontrolle einer Methode
Der Code lautet wie folgt:
<?php trait HelloWorld { public function sayHello() { echo 'Hello World!'; } } // 修改 sayHello 的访问控制 class MyClass1 { use HelloWorld { sayHello as protected; } } // 给方法一个改变了访问控制的别名 // 原版 sayHello 的访问控制则没有发生变化 class MyClass2 { use HelloWorld { sayHello as private myPrivateHello; } } ?>
Trait aus Trait zusammensetzen
So wie Klassen Merkmale verwenden können, können auch andere Merkmale Merkmale verwenden. Durch die Verwendung eines oder mehrerer Merkmale bei der Definition eines Merkmals können einige oder alle Mitglieder anderer Merkmale kombiniert werden.
Ein Beispiel für das Zusammensetzen von Merkmalen aus Merkmalen
Der Code lautet wie folgt:
<?php trait Hello { public function sayHello() { echo 'Hello '; } } trait World { public function sayWorld() { echo 'World!'; } } trait HelloWorld { use Hello, World; } class MyHelloWorld { use HelloWorld; } $o = new MyHelloWorld(); $o->sayHello(); $o->sayWorld(); ?>
Die obige Routine gibt Folgendes aus: Hallo Welt!
Abstraktion von Trait-Mitgliedern
Um Anforderungen an die verwendeten Klassen durchzusetzen, unterstützen Traits die Verwendung abstrakter Methoden.
Zeigt ein Beispiel für die Durchsetzung von Anforderungen durch abstrakte Methoden an
Der Code lautet wie folgt:
<?php trait Hello { public function sayHelloWorld() { echo 'Hello'.$this->getWorld(); } abstract public function getWorld(); } class MyHelloWorld { private $world; use Hello; public function getWorld() { return $this->world; } public function setWorld($val) { $this->world = $val; } } ?>
Statisches Mitglied von Trait
Merkmale können durch statische Mitglieder und statische Methoden definiert werden.
Ein Beispiel für eine statische Variable
Der Code lautet wie folgt:
<?php trait Counter { public function inc() { static $c = 0; $c = $c + 1; echo "$c\n"; } } class C1 { use Counter; } class C2 { use Counter; } $o = new C1(); $o->inc(); // echo 1 $p = new C2(); $p->inc(); // echo 1 ?>
Ein Beispiel für eine statische Methode
Der Code lautet wie folgt folgt:
<?php trait StaticExample { public static function doSomething() { return 'Doing something'; } } class Example { use StaticExample; } Example::doSomething(); ?>
Beispiele für statische Variablen und statische Methoden
Der Code lautet wie folgt:
<?php trait Counter { public static $c = 0; public static function inc() { self::$c = self::$c + 1; echo self::$c . "\n"; } } class C1 { use Counter; } class C2 { use Counter; } C1::inc(); // echo 1 C2::inc(); // echo 1 ?>
Attribute
Trait kann auch Attribute definieren .
Beispiel für die Definition von Attributen
Der Code lautet wie folgt:
<?php trait PropertiesTrait { public $x = 1; } class PropertiesExample { use PropertiesTrait; } $example = new PropertiesExample; $example->x; ?>
Wenn ein Merkmal ein Attribut definiert, kann die Klasse kein Attribut mit definieren derselbe Name, sonst ein Fehler. Wenn die Definition der Eigenschaft in der Klasse mit ihrer Definition im Merkmal kompatibel ist (gleiche Sichtbarkeit und gleicher Anfangswert), dann ist die Fehlerstufe E_STRICT, andernfalls handelt es sich um einen schwerwiegenden Fehler.
Beispiele für Konflikte
Der Code lautet wie folgt:
<?php trait PropertiesTrait { public $same = true; public $different = false; } class PropertiesExample { use PropertiesTrait; public $same = true; // Strict Standards public $different = true; // 致命错误 } ?>
Unterschiede in der Verwendung
Beispiele verschiedener Verwendungszwecke
Der Code lautet wie folgt:
<?php namespace Foo\Bar; use Foo\Test; // means \Foo\Test - the initial \ is optional ?> <?php namespace Foo\Bar; class SomeClass { use Foo\Test; // means \Foo\Bar\Foo\Test } ?>
Die erste Verwendung ist die Verwendung von FooTest für den Namespace, was gefunden wird, ist FooTest, die zweite Verwendung ist die Verwendung eines Merkmals, was gefunden wird istFooBarFooTest
.
__CLASS__
und __TRAIT__
__CLASS__
geben den Klassennamen des verwendeten Merkmals zurück, __TRAIT__ gibt den Merkmalsnamen zurück
Das Beispiel ist wie folgt
Der Code lautet wie folgt:
<?php trait TestTrait { public function testMethod() { echo "Class: " . __CLASS__ . PHP_EOL; echo "Trait: " . __TRAIT__ . PHP_EOL; } } class BaseClass { use TestTrait; } class TestClass extends BaseClass { } $t = new TestClass(); $t->testMethod(); //Class: BaseClass //Trait: TestTrait
Trait Singleton
Das Beispiel lautet wie folgt
Der Code lautet wie folgt:
<?php trait singleton { /** * private construct, generally defined by using class */ //private function __construct() {} public static function getInstance() { static $_instance = NULL; $class = __CLASS__; return $_instance ?: $_instance = new $class; } public function __clone() { trigger_error('Cloning '.__CLASS__.' is not allowed.',E_USER_ERROR); } public function __wakeup() { trigger_error('Unserializing '.__CLASS__.' is not allowed.',E_USER_ERROR); } } /** * Example Usage */ class foo { use singleton; private function __construct() { $this->name = 'foo'; } } class bar { use singleton; private function __construct() { $this->name = 'bar'; } } $foo = foo::getInstance(); echo $foo->name; $bar = bar::getInstance(); echo $bar->name;
Trait-Methoden aufrufen
Obwohl es nicht offensichtlich ist, kann es sein, dass die Trait-Methode als statische Methode in einer normalen Klasse definiert werden kann genannt
实例如下
代码如下:
<?php trait Foo { function bar() { return 'baz'; } } echo Foo::bar(),"\\n"; ?>
相关学习推荐:PHP编程从入门到精通
Das obige ist der detaillierte Inhalt vonSo implementieren Sie neue Merkmale der Code-Wiederverwendung in PHP. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!